(esc-map): Change ; to comment-dwim and use the new function
[emacs.git] / src / w32term.c
blobe2e4c168c5c92fe3ac0df78a3c59b86465988496
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 97, 98 Free Software Foundation, Inc.
4 This file is part of GNU Emacs.
6 GNU Emacs is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
21 #include <config.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include "lisp.h"
26 #include "charset.h"
27 #include "blockinput.h"
29 #include "w32heap.h"
30 #include "w32term.h"
31 #include "w32bdf.h"
32 #include <shellapi.h>
34 #include "systty.h"
35 #include "systime.h"
36 #include "atimer.h"
38 #include <ctype.h>
39 #include <errno.h>
40 #include <setjmp.h>
41 #include <sys/stat.h>
43 #include "frame.h"
44 #include "dispextern.h"
45 #include "fontset.h"
46 #include "termhooks.h"
47 #include "termopts.h"
48 #include "termchar.h"
49 #include "gnu.h"
50 #include "disptab.h"
51 #include "buffer.h"
52 #include "window.h"
53 #include "keyboard.h"
54 #include "intervals.h"
55 #include "composite.h"
56 #include "coding.h"
58 #undef min
59 #undef max
60 #define min(x, y) (((x) < (y)) ? (x) : (y))
61 #define max(x, y) (((x) > (y)) ? (x) : (y))
63 #define abs(x) ((x) < 0 ? -(x) : (x))
65 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
68 /* Bitmaps for truncated lines. */
70 enum bitmap_type
72 NO_BITMAP,
73 LEFT_TRUNCATION_BITMAP,
74 RIGHT_TRUNCATION_BITMAP,
75 OVERLAY_ARROW_BITMAP,
76 CONTINUED_LINE_BITMAP,
77 CONTINUATION_LINE_BITMAP,
78 ZV_LINE_BITMAP
81 /* Bitmaps are all unsigned short, as Windows requires bitmap data to
82 be Word aligned. For some reason they are horizontally reflected
83 compared to how they appear on X, so changes in xterm.c should be
84 reflected here. */
86 /* Bitmap drawn to indicate lines not displaying text if
87 `indicate-empty-lines' is non-nil. */
89 #define zv_width 8
90 #define zv_height 8
91 static unsigned short zv_bits[] = {
92 0x00, 0x00, 0x78, 0x78, 0x78, 0x78, 0x00, 0x00};
93 static HBITMAP zv_bmp;
95 /* An arrow like this: `<-'. */
97 #define left_width 8
98 #define left_height 8
99 static unsigned short left_bits[] = {
100 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
101 static HBITMAP left_bmp;
103 /* Right truncation arrow bitmap `->'. */
105 #define right_width 8
106 #define right_height 8
107 static unsigned short right_bits[] = {
108 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
109 static HBITMAP right_bmp;
111 /* Marker for continued lines. */
113 #define continued_width 8
114 #define continued_height 8
115 static unsigned short continued_bits[] = {
116 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
117 static HBITMAP continued_bmp;
119 /* Marker for continuation lines. */
121 #define continuation_width 8
122 #define continuation_height 8
123 static unsigned short continuation_bits[] = {
124 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
125 static HBITMAP continuation_bmp;
127 /* Overlay arrow bitmap. */
129 #if 0
130 /* A bomb. */
131 #define ov_width 8
132 #define ov_height 8
133 static unsigned short ov_bits[] = {
134 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
135 #else
136 /* A triangular arrow. */
137 #define ov_width 8
138 #define ov_height 8
139 static unsigned short ov_bits[] = {
140 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
141 #endif
142 static HBITMAP ov_bmp;
144 extern Lisp_Object Qhelp_echo;
147 /* Non-zero means Emacs uses toolkit scroll bars. */
149 int x_toolkit_scroll_bars_p;
151 /* If a string, w32_read_socket generates an event to display that string.
152 (The display is done in read_char.) */
154 static Lisp_Object help_echo;
156 /* Temporary variable for w32_read_socket. */
158 static Lisp_Object previous_help_echo;
160 /* Non-zero means that a HELP_EVENT has been generated since Emacs
161 start. */
163 static int any_help_event_p;
165 /* Non-zero means draw block and hollow cursor as wide as the glyph
166 under it. For example, if a block cursor is over a tab, it will be
167 drawn as wide as that tab on the display. */
169 int x_stretch_cursor_p;
171 #define CP_DEFAULT 1004
173 extern unsigned int msh_mousewheel;
175 extern void free_frame_menubar ();
177 extern void w32_menu_display_help (HMENU menu, UINT menu_item, UINT flags);
179 extern Lisp_Object Vwindow_system;
181 #define x_any_window_to_frame x_window_to_frame
182 #define x_top_window_to_frame x_window_to_frame
185 /* This is display since w32 does not support multiple ones. */
186 struct w32_display_info one_w32_display_info;
188 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
189 one for each element of w32_display_list and in the same order.
190 NAME is the name of the frame.
191 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
192 Lisp_Object w32_display_name_list;
194 /* Frame being updated by update_frame. This is declared in term.c.
195 This is set by update_begin and looked at by all the
196 w32 functions. It is zero while not inside an update.
197 In that case, the w32 functions assume that `SELECTED_FRAME ()'
198 is the frame to apply to. */
199 extern struct frame *updating_frame;
201 /* This is a frame waiting to be autoraised, within w32_read_socket. */
202 struct frame *pending_autoraise_frame;
204 /* Nominal cursor position -- where to draw output.
205 HPOS and VPOS are window relative glyph matrix coordinates.
206 X and Y are window relative pixel coordinates. */
208 struct cursor_pos output_cursor;
210 /* Flag to enable Unicode output in case users wish to use programs
211 like Twinbridge on '95 rather than installed system level support
212 for Far East languages. */
213 int w32_enable_unicode_output;
215 DWORD dwWindowsThreadId = 0;
216 HANDLE hWindowsThread = NULL;
217 DWORD dwMainThreadId = 0;
218 HANDLE hMainThread = NULL;
220 #ifndef SIF_ALL
221 /* These definitions are new with Windows 95. */
222 #define SIF_RANGE 0x0001
223 #define SIF_PAGE 0x0002
224 #define SIF_POS 0x0004
225 #define SIF_DISABLENOSCROLL 0x0008
226 #define SIF_TRACKPOS 0x0010
227 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
229 typedef struct tagSCROLLINFO
231 UINT cbSize;
232 UINT fMask;
233 int nMin;
234 int nMax;
235 UINT nPage;
236 int nPos;
237 int nTrackPos;
238 } SCROLLINFO, FAR *LPSCROLLINFO;
239 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
240 #endif /* SIF_ALL */
242 /* Dynamic linking to new proportional scroll bar functions. */
243 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
244 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
246 int vertical_scroll_bar_min_handle;
247 int vertical_scroll_bar_top_border;
248 int vertical_scroll_bar_bottom_border;
250 int last_scroll_bar_drag_pos;
252 /* Mouse movement. */
254 /* Where the mouse was last time we reported a mouse event. */
255 FRAME_PTR last_mouse_frame;
256 static RECT last_mouse_glyph;
257 static Lisp_Object last_mouse_press_frame;
259 Lisp_Object Vw32_num_mouse_buttons;
261 Lisp_Object Vw32_swap_mouse_buttons;
263 /* Control whether x_raise_frame also sets input focus. */
264 Lisp_Object Vw32_grab_focus_on_raise;
266 /* Control whether Caps Lock affects non-ascii characters. */
267 Lisp_Object Vw32_capslock_is_shiftlock;
269 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
270 Lisp_Object Vw32_recognize_altgr;
272 /* The scroll bar in which the last motion event occurred.
274 If the last motion event occurred in a scroll bar, we set this
275 so w32_mouse_position can know whether to report a scroll bar motion or
276 an ordinary motion.
278 If the last motion event didn't occur in a scroll bar, we set this
279 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
280 Lisp_Object last_mouse_scroll_bar;
281 int last_mouse_scroll_bar_pos;
283 /* This is a hack. We would really prefer that w32_mouse_position would
284 return the time associated with the position it returns, but there
285 doesn't seem to be any way to wrest the timestamp from the server
286 along with the position query. So, we just keep track of the time
287 of the last movement we received, and return that in hopes that
288 it's somewhat accurate. */
289 Time last_mouse_movement_time;
291 /* Associative list linking character set strings to Windows codepages. */
292 Lisp_Object Vw32_charset_info_alist;
294 /* Incremented by w32_read_socket whenever it really tries to read events. */
295 #ifdef __STDC__
296 static int volatile input_signal_count;
297 #else
298 static int input_signal_count;
299 #endif
301 extern Lisp_Object Vcommand_line_args, Vsystem_name;
303 extern Lisp_Object Qface, Qmouse_face;
305 extern int errno;
307 /* A mask of extra modifier bits to put into every keyboard char. */
308 extern int extra_keyboard_modifiers;
310 /* Enumeration for overriding/changing the face to use for drawing
311 glyphs in x_draw_glyphs. */
313 enum draw_glyphs_face
315 DRAW_NORMAL_TEXT,
316 DRAW_INVERSE_VIDEO,
317 DRAW_CURSOR,
318 DRAW_MOUSE_FACE,
319 DRAW_IMAGE_RAISED,
320 DRAW_IMAGE_SUNKEN
323 static void x_update_window_end P_ ((struct window *, int));
324 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
325 void w32_delete_display P_ ((struct w32_display_info *));
326 static int fast_find_position P_ ((struct window *, int, int *, int *,
327 int *, int *));
328 static void set_output_cursor P_ ((struct cursor_pos *));
329 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
330 int *, int *, int *));
331 static void note_mode_line_highlight P_ ((struct window *, int, int));
332 static void x_check_font P_ ((struct frame *, XFontStruct *));
333 static void note_mouse_highlight P_ ((struct frame *, int, int));
334 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
335 static void w32_handle_tool_bar_click P_ ((struct frame *,
336 struct input_event *));
337 static void show_mouse_face P_ ((struct w32_display_info *,
338 enum draw_glyphs_face));
339 void clear_mouse_face P_ ((struct w32_display_info *));
341 void x_lower_frame P_ ((struct frame *));
342 void x_scroll_bar_clear P_ ((struct frame *));
343 void x_wm_set_size_hint P_ ((struct frame *, long, int));
344 void x_raise_frame P_ ((struct frame *));
345 void x_set_window_size P_ ((struct frame *, int, int, int));
346 void x_wm_set_window_state P_ ((struct frame *, int));
347 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
348 void w32_initialize P_ ((void));
349 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
350 int x_compute_min_glyph_bounds P_ ((struct frame *));
351 static void x_draw_phys_cursor_glyph P_ ((struct window *,
352 struct glyph_row *,
353 enum draw_glyphs_face));
354 static void x_update_end P_ ((struct frame *));
355 static void w32_frame_up_to_date P_ ((struct frame *));
356 static void w32_reassert_line_highlight P_ ((int, int));
357 static void x_change_line_highlight P_ ((int, int, int, int));
358 static void w32_set_terminal_modes P_ ((void));
359 static void w32_reset_terminal_modes P_ ((void));
360 static void w32_cursor_to P_ ((int, int, int, int));
361 static void x_write_glyphs P_ ((struct glyph *, int));
362 static void x_clear_end_of_line P_ ((int));
363 static void x_clear_frame P_ ((void));
364 static void x_clear_cursor P_ ((struct window *));
365 static void frame_highlight P_ ((struct frame *));
366 static void frame_unhighlight P_ ((struct frame *));
367 static void w32_new_focus_frame P_ ((struct w32_display_info *,
368 struct frame *));
369 static void w32_frame_rehighlight P_ ((struct frame *));
370 static void x_frame_rehighlight P_ ((struct w32_display_info *));
371 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
372 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *));
373 static int w32_intersect_rectangles P_ ((RECT *, RECT *, RECT *));
374 static void expose_frame P_ ((struct frame *, int, int, int, int));
375 static void expose_window_tree P_ ((struct window *, RECT *));
376 static void expose_window P_ ((struct window *, RECT *));
377 static void expose_area P_ ((struct window *, struct glyph_row *,
378 RECT *, enum glyph_row_area));
379 static void expose_line P_ ((struct window *, struct glyph_row *,
380 RECT *));
381 void x_update_cursor P_ ((struct frame *, int));
382 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
383 static void x_update_window_cursor P_ ((struct window *, int));
384 static void x_erase_phys_cursor P_ ((struct window *));
385 void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
386 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
387 static void w32_draw_bitmap P_ ((struct window *, HDC hdc, struct glyph_row *,
388 enum bitmap_type));
389 static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
390 static void x_draw_row_bitmaps P_ ((struct window *, struct glyph_row *));
391 static void note_overwritten_text_cursor P_ ((struct window *, int, int));
392 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
393 HDC, int));
395 static Lisp_Object Qvendor_specific_keysyms;
397 Lisp_Object Qw32_charset_ansi;
398 Lisp_Object Qw32_charset_default;
399 Lisp_Object Qw32_charset_symbol;
400 Lisp_Object Qw32_charset_shiftjis;
401 Lisp_Object Qw32_charset_hangul;
402 Lisp_Object Qw32_charset_gb2312;
403 Lisp_Object Qw32_charset_chinesebig5;
404 Lisp_Object Qw32_charset_oem;
406 #ifdef JOHAB_CHARSET
407 Lisp_Object Qw32_charset_easteurope;
408 Lisp_Object Qw32_charset_turkish;
409 Lisp_Object Qw32_charset_baltic;
410 Lisp_Object Qw32_charset_russian;
411 Lisp_Object Qw32_charset_arabic;
412 Lisp_Object Qw32_charset_greek;
413 Lisp_Object Qw32_charset_hebrew;
414 Lisp_Object Qw32_charset_thai;
415 Lisp_Object Qw32_charset_johab;
416 Lisp_Object Qw32_charset_mac;
417 #endif
419 #ifdef UNICODE_CHARSET
420 Lisp_Object Qw32_charset_unicode;
421 #endif
424 #if 0
425 /* This is a function useful for recording debugging information
426 about the sequence of occurrences in this file. */
428 struct record
430 char *locus;
431 int type;
434 struct record event_record[100];
436 int event_record_index;
438 record_event (locus, type)
439 char *locus;
440 int type;
442 if (event_record_index == sizeof (event_record) / sizeof (struct record))
443 event_record_index = 0;
445 event_record[event_record_index].locus = locus;
446 event_record[event_record_index].type = type;
447 event_record_index++;
450 #endif /* 0 */
453 void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
454 XGCValues *xgcv)
456 if (mask & GCForeground)
457 gc->foreground = xgcv->foreground;
458 if (mask & GCBackground)
459 gc->background = xgcv->background;
460 if (mask & GCFont)
461 gc->font = xgcv->font;
464 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
465 XGCValues *xgcv)
467 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
468 bzero (gc, sizeof (XGCValues));
470 XChangeGC (ignore, gc, mask, xgcv);
472 return gc;
475 void XGetGCValues (void* ignore, XGCValues *gc,
476 unsigned long mask, XGCValues *xgcv)
478 XChangeGC (ignore, xgcv, mask, gc);
481 void XTextExtents16 (XFontStruct *font, wchar_t *text, int nchars,
482 int *direction,int *font_ascent,
483 int *font_descent, XCharStruct *cs)
485 /* NTEMACS_TODO: Use GetTextMetrics to do this and inline it below. */
488 static void
489 w32_set_clip_rectangle (HDC hdc, RECT *rect)
491 if (rect)
493 HRGN clip_region = CreateRectRgnIndirect (rect);
494 SelectClipRgn (hdc, clip_region);
495 DeleteObject (clip_region);
497 else
498 SelectClipRgn (hdc, NULL);
502 /* Draw a hollow rectangle at the specified position. */
503 void
504 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
505 int width, int height)
507 HBRUSH hb, oldhb;
508 HPEN hp, oldhp;
510 hb = CreateSolidBrush (gc->background);
511 hp = CreatePen (PS_SOLID, 0, gc->foreground);
512 oldhb = SelectObject (hdc, hb);
513 oldhp = SelectObject (hdc, hp);
515 Rectangle (hdc, x, y, x + width, y + height);
517 SelectObject (hdc, oldhb);
518 SelectObject (hdc, oldhp);
519 DeleteObject (hb);
520 DeleteObject (hp);
523 /* Draw a filled rectangle at the specified position. */
524 void
525 w32_fill_rect (f, hdc, pix, lprect)
526 FRAME_PTR f;
527 HDC hdc;
528 COLORREF pix;
529 RECT * lprect;
531 HBRUSH hb;
532 RECT rect;
534 hb = CreateSolidBrush (pix);
535 FillRect (hdc, lprect, hb);
536 DeleteObject (hb);
539 void
540 w32_clear_window (f)
541 FRAME_PTR f;
543 RECT rect;
544 HDC hdc = get_frame_dc (f);
546 GetClientRect (FRAME_W32_WINDOW (f), &rect);
547 w32_clear_rect (f, hdc, &rect);
548 release_frame_dc (f, hdc);
552 /***********************************************************************
553 Starting and ending an update
554 ***********************************************************************/
556 /* Start an update of frame F. This function is installed as a hook
557 for update_begin, i.e. it is called when update_begin is called.
558 This function is called prior to calls to x_update_window_begin for
559 each window being updated. Currently, there is nothing to do here
560 because all interesting stuff is done on a window basis. */
562 static void
563 x_update_begin (f)
564 struct frame *f;
566 /* Nothing to do. We have to do something though, otherwise the
567 function gets optimized away and the hook is no longer valid. */
568 struct frame *cf = f;
572 /* Start update of window W. Set the global variable updated_window
573 to the window being updated and set output_cursor to the cursor
574 position of W. */
576 static void
577 x_update_window_begin (w)
578 struct window *w;
580 struct frame *f = XFRAME (WINDOW_FRAME (w));
581 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
583 updated_window = w;
584 set_output_cursor (&w->cursor);
586 BLOCK_INPUT;
588 /* Regenerate display palette before drawing if list of requested
589 colors has changed. */
590 if (display_info->regen_palette)
592 w32_regenerate_palette (f);
593 display_info->regen_palette = FALSE;
596 if (f == display_info->mouse_face_mouse_frame)
598 /* Don't do highlighting for mouse motion during the update. */
599 display_info->mouse_face_defer = 1;
601 /* If the frame needs to be redrawn,
602 simply forget about any prior mouse highlighting. */
603 if (FRAME_GARBAGED_P (f))
604 display_info->mouse_face_window = Qnil;
606 /* Can we tell that this update does not affect the window
607 where the mouse highlight is? If so, no need to turn off.
608 Likewise, don't do anything if the frame is garbaged;
609 in that case, the frame's current matrix that we would use
610 is all wrong, and we will redisplay that line anyway. */
611 if (!NILP (display_info->mouse_face_window)
612 && w == XWINDOW (display_info->mouse_face_window))
614 int i;
616 for (i = 0; i < w->desired_matrix->nrows; ++i)
617 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
618 break;
620 if (i < w->desired_matrix->nrows)
621 clear_mouse_face (display_info);
625 UNBLOCK_INPUT;
629 /* Draw a vertical window border to the right of window W if W doesn't
630 have vertical scroll bars. */
632 static void
633 x_draw_vertical_border (w)
634 struct window *w;
636 struct frame *f = XFRAME (WINDOW_FRAME (w));
638 /* Redraw borders between horizontally adjacent windows. Don't
639 do it for frames with vertical scroll bars because either the
640 right scroll bar of a window, or the left scroll bar of its
641 neighbor will suffice as a border. */
642 if (!WINDOW_RIGHTMOST_P (w)
643 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
645 RECT r;
646 HDC hdc;
648 window_box_edges (w, -1, &r.left, &r.top, &r.right, &r.bottom);
649 r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
650 r.right = r.left + 1;
651 r.bottom -= 1;
653 hdc = get_frame_dc (f);
654 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), r);
655 release_frame_dc (f, hdc);
660 /* End update of window W (which is equal to updated_window). Draw
661 vertical borders between horizontally adjacent windows, and display
662 W's cursor if CURSOR_ON_P is non-zero. W may be a menu bar
663 pseudo-window in case we don't have X toolkit support. Such
664 windows don't have a cursor, so don't display it here. */
666 static void
667 x_update_window_end (w, cursor_on_p)
668 struct window *w;
669 int cursor_on_p;
671 if (!w->pseudo_window_p)
673 BLOCK_INPUT;
674 if (cursor_on_p)
675 x_display_and_set_cursor (w, 1, output_cursor.hpos,
676 output_cursor.vpos,
677 output_cursor.x, output_cursor.y);
678 x_draw_vertical_border (w);
679 UNBLOCK_INPUT;
682 updated_window = NULL;
685 static void
686 x_update_end (f)
687 struct frame *f;
689 /* Mouse highlight may be displayed again. */
690 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
693 /* This function is called from various places in xdisp.c whenever a
694 complete update has been performed. The global variable
695 updated_window is not available here. */
697 static void
698 w32_frame_up_to_date (f)
699 struct frame *f;
701 if (FRAME_W32_P (f))
703 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
704 if (dpyinfo->mouse_face_deferred_gc
705 || f == dpyinfo->mouse_face_mouse_frame)
707 BLOCK_INPUT;
708 if (dpyinfo->mouse_face_mouse_frame)
709 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
710 dpyinfo->mouse_face_mouse_x,
711 dpyinfo->mouse_face_mouse_y);
712 dpyinfo->mouse_face_deferred_gc = 0;
713 UNBLOCK_INPUT;
719 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
720 arrow bitmaps, or clear the areas where they would be displayed
721 before DESIRED_ROW is made current. The window being updated is
722 found in updated_window. This function It is called from
723 update_window_line only if it is known that there are differences
724 between bitmaps to be drawn between current row and DESIRED_ROW. */
726 static void
727 x_after_update_window_line (desired_row)
728 struct glyph_row *desired_row;
730 struct window *w = updated_window;
732 xassert (w);
734 if (!desired_row->mode_line_p && !w->pseudo_window_p)
736 BLOCK_INPUT;
737 x_draw_row_bitmaps (w, desired_row);
739 /* When a window has disappeared, make sure that no rest of
740 full-width rows stays visible in the internal border. */
741 if (windows_or_buffers_changed)
743 struct frame *f = XFRAME (w->frame);
744 int width = FRAME_INTERNAL_BORDER_WIDTH (f);
745 int height = desired_row->visible_height;
746 int x = (window_box_right (w, -1)
747 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
748 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
749 HDC hdc = get_frame_dc (f);
751 w32_clear_area (f, hdc, x, y, width, height);
752 release_frame_dc (f, hdc);
755 UNBLOCK_INPUT;
760 /* Draw the bitmap WHICH in one of the areas to the left or right of
761 window W. ROW is the glyph row for which to display the bitmap; it
762 determines the vertical position at which the bitmap has to be
763 drawn. */
765 static void
766 w32_draw_bitmap (w, hdc, row, which)
767 struct window *w;
768 HDC hdc;
769 struct glyph_row *row;
770 enum bitmap_type which;
772 struct frame *f = XFRAME (WINDOW_FRAME (w));
773 Window window = FRAME_W32_WINDOW (f);
774 HDC compat_hdc;
775 int x, y, wd, h, dy;
776 HBITMAP pixmap;
777 HBRUSH fg_brush, orig_brush;
778 HANDLE horig_obj;
779 struct face *face;
781 /* Must clip because of partially visible lines. */
782 w32_clip_to_row (w, row, hdc, 1);
784 switch (which)
786 case LEFT_TRUNCATION_BITMAP:
787 wd = left_width;
788 h = left_height;
789 pixmap = left_bmp;
790 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
791 - wd
792 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
793 break;
795 case OVERLAY_ARROW_BITMAP:
796 wd = ov_width;
797 h = ov_height;
798 pixmap = ov_bmp;
799 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
800 - wd
801 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
802 break;
804 case RIGHT_TRUNCATION_BITMAP:
805 wd = right_width;
806 h = right_height;
807 pixmap = right_bmp;
808 x = window_box_right (w, -1);
809 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
810 break;
812 case CONTINUED_LINE_BITMAP:
813 wd = continued_width;
814 h = continued_height;
815 pixmap = continued_bmp;
816 x = window_box_right (w, -1);
817 x += (FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f) - wd) / 2;
818 break;
820 case CONTINUATION_LINE_BITMAP:
821 wd = continuation_width;
822 h = continuation_height;
823 pixmap = continuation_bmp;
824 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
825 - wd
826 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
827 break;
829 case ZV_LINE_BITMAP:
830 wd = zv_width;
831 h = zv_height;
832 pixmap = zv_bmp;
833 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
834 - wd
835 - (FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - wd) / 2);
836 break;
838 default:
839 abort ();
842 /* Convert to frame coordinates. Set dy to the offset in the row to
843 start drawing the bitmap. */
844 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
845 dy = (row->height - h) / 2;
847 /* Draw the bitmap. */
848 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
850 compat_hdc = CreateCompatibleDC (hdc);
851 SaveDC (hdc);
852 fg_brush = CreateSolidBrush (FRAME_FOREGROUND_PIXEL (f));
853 orig_brush = SelectObject (hdc, fg_brush);
854 horig_obj = SelectObject (compat_hdc, pixmap);
855 SetTextColor (hdc, FRAME_BACKGROUND_PIXEL (f));
856 SetBkColor (hdc, FRAME_FOREGROUND_PIXEL (f));
857 #if 0 /* From w32bdf.c (which is from Meadow). */
858 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, SRCCOPY);
859 #else
860 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0, 0, 0xB8074A);
861 #endif
862 SelectObject (compat_hdc, horig_obj);
863 SelectObject (hdc, orig_brush);
864 DeleteObject (fg_brush);
865 DeleteDC (compat_hdc);
866 RestoreDC (hdc, -1);
870 /* Draw flags bitmaps for glyph row ROW on window W. Call this
871 function with input blocked. */
873 static void
874 x_draw_row_bitmaps (w, row)
875 struct window *w;
876 struct glyph_row *row;
878 struct frame *f = XFRAME (w->frame);
879 enum bitmap_type bitmap;
880 struct face *face;
881 int header_line_height = -1;
882 HDC hdc = get_frame_dc (f);
884 xassert (interrupt_input_blocked);
886 /* If row is completely invisible, because of vscrolling, we
887 don't have to draw anything. */
888 if (row->visible_height <= 0)
889 return;
891 face = FACE_FROM_ID (f, BITMAP_AREA_FACE_ID);
892 PREPARE_FACE_FOR_DISPLAY (f, face);
894 /* Decide which bitmap to draw at the left side. */
895 if (row->overlay_arrow_p)
896 bitmap = OVERLAY_ARROW_BITMAP;
897 else if (row->truncated_on_left_p)
898 bitmap = LEFT_TRUNCATION_BITMAP;
899 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
900 bitmap = CONTINUATION_LINE_BITMAP;
901 else if (row->indicate_empty_line_p)
902 bitmap = ZV_LINE_BITMAP;
903 else
904 bitmap = NO_BITMAP;
906 /* Clear flags area if no bitmap to draw or if bitmap doesn't fill
907 the flags area. */
908 if (bitmap == NO_BITMAP
909 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
910 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
912 /* If W has a vertical border to its left, don't draw over it. */
913 int border = ((XFASTINT (w->left) > 0
914 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
915 ? 1 : 0);
916 int left = window_box_left (w, -1);
918 if (header_line_height < 0)
919 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
921 w32_fill_area (f, hdc, face->background,
922 left - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) + border,
923 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
924 row->y)),
925 FRAME_X_LEFT_FLAGS_AREA_WIDTH (f) - border,
926 row->visible_height);
929 /* Draw the left bitmap. */
930 if (bitmap != NO_BITMAP)
931 w32_draw_bitmap (w, hdc, row, bitmap);
933 /* Decide which bitmap to draw at the right side. */
934 if (row->truncated_on_right_p)
935 bitmap = RIGHT_TRUNCATION_BITMAP;
936 else if (row->continued_p)
937 bitmap = CONTINUED_LINE_BITMAP;
938 else
939 bitmap = NO_BITMAP;
941 /* Clear flags area if no bitmap to draw of if bitmap doesn't fill
942 the flags area. */
943 if (bitmap == NO_BITMAP
944 || FRAME_FLAGS_BITMAP_WIDTH (f) < FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)
945 || row->height > FRAME_FLAGS_BITMAP_HEIGHT (f))
947 int right = window_box_right (w, -1);
949 if (header_line_height < 0)
950 header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
952 w32_fill_area (f, hdc, face->background,
953 right,
954 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
955 row->y)),
956 FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f),
957 row->visible_height);
960 /* Draw the right bitmap. */
961 if (bitmap != NO_BITMAP)
962 w32_draw_bitmap (w, hdc, row, bitmap);
964 release_frame_dc (f, hdc);
969 /***********************************************************************
970 Line Highlighting
971 ***********************************************************************/
973 /* External interface to control of standout mode. Not used for W32
974 frames. Aborts when called. */
976 static void
977 w32_reassert_line_highlight (new, vpos)
978 int new, vpos;
980 abort ();
983 /* Call this when about to modify line at position VPOS and change
984 whether it is highlighted. Not used for W32 frames. Aborts when
985 called. */
987 static void
988 x_change_line_highlight (new_highlight, vpos, y, first_unused_hpos)
989 int new_highlight, vpos, y, first_unused_hpos;
991 abort ();
994 /* This is used when starting Emacs and when restarting after suspend.
995 When starting Emacs, no window is mapped. And nothing must be done
996 to Emacs's own window if it is suspended (though that rarely happens). */
998 static void
999 w32_set_terminal_modes (void)
1003 /* This is called when exiting or suspending Emacs.
1004 Exiting will make the W32 windows go away, and suspending
1005 requires no action. */
1007 static void
1008 w32_reset_terminal_modes (void)
1013 /***********************************************************************
1014 Output Cursor
1015 ***********************************************************************/
1017 /* Set the global variable output_cursor to CURSOR. All cursor
1018 positions are relative to updated_window. */
1019 static void
1020 set_output_cursor (cursor)
1021 struct cursor_pos *cursor;
1023 output_cursor.hpos = cursor->hpos;
1024 output_cursor.vpos = cursor->vpos;
1025 output_cursor.x = cursor->x;
1026 output_cursor.y = cursor->y;
1030 /* Set a nominal cursor position.
1032 HPOS and VPOS are column/row positions in a window glyph matrix. X
1033 and Y are window text area relative pixel positions.
1035 If this is done during an update, updated_window will contain the
1036 window that is being updated and the position is the future output
1037 cursor position for that window. If updated_window is null, use
1038 selected_window and display the cursor at the given position. */
1040 static void
1041 w32_cursor_to (vpos, hpos, y, x)
1042 int vpos, hpos, y, x;
1044 struct window *w;
1046 /* If updated_window is not set, work on selected_window. */
1047 if (updated_window)
1048 w = updated_window;
1049 else
1050 w = XWINDOW (selected_window);
1052 /* Set the output cursor. */
1053 output_cursor.hpos = hpos;
1054 output_cursor.vpos = vpos;
1055 output_cursor.x = x;
1056 output_cursor.y = y;
1058 /* If not called as part of an update, really display the cursor.
1059 This will also set the cursor position of W. */
1060 if (updated_window == NULL)
1062 BLOCK_INPUT;
1063 x_display_cursor (w, 1, hpos, vpos, x, y);
1064 UNBLOCK_INPUT;
1069 /***********************************************************************
1070 Display Iterator
1071 ***********************************************************************/
1073 /* Function prototypes of this page. */
1075 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1076 struct glyph *,
1077 wchar_t *,
1078 int *));
1079 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1080 int, wchar_t *, int));
1081 static XCharStruct *w32_per_char_metric P_ ((HDC hdc, XFontStruct *,
1082 wchar_t *, int unicode_p));
1083 static void x_encode_char P_ ((int, wchar_t *, struct font_info *));
1084 static void x_append_glyph P_ ((struct it *));
1085 static void x_append_composite_glyph P_ ((struct it *));
1086 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1087 int, int, double));
1088 static void x_produce_glyphs P_ ((struct it *));
1089 static void x_produce_image_glyph P_ ((struct it *it));
1092 /* Dealing with bits of wchar_t as if they were an XChar2B. */
1093 #define BUILD_WCHAR_T(byte1, byte2) \
1094 ((wchar_t)((((byte1) & 0x00ff) << 8) | ((byte2) & 0x00ff)))
1097 #define BYTE1(ch) \
1098 (((ch) & 0xff00) >> 8)
1100 #define BYTE2(ch) \
1101 ((ch) & 0x00ff)
1104 /* NTEMACS_TODO: Add support for bdf fonts back in. */
1106 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1107 If CHAR2B is not contained in FONT, the font's default character
1108 metric is returned. If unicode_p is non-zero, use unicode functions,
1109 otherwise use ANSI functions. */
1111 static INLINE XCharStruct *
1112 w32_per_char_metric (hdc, font, char2b, unicode_p)
1113 HDC hdc;
1114 XFontStruct *font;
1115 wchar_t *char2b;
1116 int unicode_p;
1118 /* The result metric information. */
1119 XCharStruct *pcm;
1120 ABC char_widths;
1121 SIZE sz;
1122 BOOL retval;
1124 xassert (font && char2b);
1126 pcm = (XCharStruct *) xmalloc (sizeof (XCharStruct));
1128 if (font->hfont)
1129 SelectObject (hdc, font->hfont);
1131 if (unicode_p)
1132 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
1133 else
1134 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
1136 if (retval)
1138 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
1139 pcm->lbearing = char_widths.abcA;
1140 pcm->rbearing = pcm->width - char_widths.abcC;
1142 else
1144 /* Windows 9x does not implement GetCharABCWidthsW, so if that
1145 failed, try GetTextExtentPoint32W, which is implemented and
1146 at least gives us some of the info we are after (total
1147 character width). */
1148 if (unicode_p)
1149 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
1151 if (retval)
1153 pcm->width = sz.cx;
1154 pcm->rbearing = sz.cx;
1155 pcm->lbearing = 0;
1157 else
1159 pcm->width = FONT_MAX_WIDTH (font);
1160 pcm->rbearing = FONT_MAX_WIDTH (font);
1161 pcm->lbearing = 0;
1165 pcm->ascent = FONT_BASE (font);
1166 pcm->descent = FONT_DESCENT (font);
1168 if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1170 xfree (pcm);
1171 pcm = NULL;
1174 return pcm;
1178 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1179 the two-byte form of C. Encoding is returned in *CHAR2B. */
1181 static INLINE void
1182 x_encode_char (c, char2b, font_info)
1183 int c;
1184 wchar_t *char2b;
1185 struct font_info *font_info;
1187 int charset = CHAR_CHARSET (c);
1188 int codepage;
1189 XFontStruct *font = font_info->font;
1191 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1192 This may be either a program in a special encoder language or a
1193 fixed encoding. */
1194 if (font_info->font_encoder)
1196 /* It's a program. */
1197 struct ccl_program *ccl = font_info->font_encoder;
1199 if (CHARSET_DIMENSION (charset) == 1)
1201 ccl->reg[0] = charset;
1202 ccl->reg[1] = BYTE2 (*char2b);
1204 else
1206 ccl->reg[0] = charset;
1207 ccl->reg[1] = BYTE1 (*char2b);
1208 ccl->reg[2] = BYTE2 (*char2b);
1211 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1213 /* We assume that MSBs are appropriately set/reset by CCL
1214 program. */
1215 /* NTEMACS_TODO : Use GetFontLanguageInfo to determine if
1216 font is double byte. */
1217 #if 0
1218 if (FONT_MAX_BYTE1 (font) == 0) /* 1-byte font */
1219 #endif
1220 *char2b = BUILD_WCHAR_T (0, ccl->reg[1]);
1221 #if 0
1222 else
1223 *char2b = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
1224 #endif
1226 else if (font_info->encoding[charset])
1228 /* Fixed encoding scheme. See fontset.h for the meaning of the
1229 encoding numbers. */
1230 int enc = font_info->encoding[charset];
1232 if ((enc == 1 || enc == 2)
1233 && CHARSET_DIMENSION (charset) == 2)
1234 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b) | 0x80, BYTE2 (*char2b));
1236 if (enc == 1 || enc == 3
1237 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
1238 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), BYTE2 (*char2b) | 0x80);
1239 else if (enc == 4)
1241 int sjis1, sjis2;
1243 ENCODE_SJIS (BYTE1 (*char2b), BYTE2 (*char2b),
1244 sjis1, sjis2);
1245 *char2b = BUILD_WCHAR_T (sjis1, sjis2);
1248 codepage = w32_codepage_for_font (font_info->name);
1250 /* If charset is not ASCII or Latin-1, may need to move it into
1251 Unicode space. */
1252 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
1253 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1)
1255 char temp[3];
1256 temp[0] = BYTE1 (*char2b);
1257 temp[1] = BYTE2 (*char2b);
1258 temp[2] = '\0';
1259 if (temp[0])
1260 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1261 else
1262 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1267 /* Get face and two-byte form of character C in face FACE_ID on frame
1268 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1269 means we want to display multibyte text. Value is a pointer to a
1270 realized face that is ready for display. */
1272 static INLINE struct face *
1273 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1274 struct frame *f;
1275 int c, face_id;
1276 wchar_t *char2b;
1277 int multibyte_p;
1279 struct face *face = FACE_FROM_ID (f, face_id);
1281 if (!multibyte_p)
1283 /* Unibyte case. We don't have to encode, but we have to make
1284 sure to use a face suitable for unibyte. */
1285 *char2b = BUILD_WCHAR_T (0, c);
1286 face_id = FACE_FOR_CHAR (f, face, c);
1287 face = FACE_FROM_ID (f, face_id);
1289 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1291 /* Case of ASCII in a face known to fit ASCII. */
1292 *char2b = BUILD_WCHAR_T (0, c);
1294 else
1296 int c1, c2, charset;
1298 /* Split characters into bytes. If c2 is -1 afterwards, C is
1299 really a one-byte character so that byte1 is zero. */
1300 SPLIT_CHAR (c, charset, c1, c2);
1301 if (c2 > 0)
1302 *char2b = BUILD_WCHAR_T (c1, c2);
1303 else
1304 *char2b = BUILD_WCHAR_T (0, c1);
1306 /* Maybe encode the character in *CHAR2B. */
1307 if (face->font != NULL)
1309 struct font_info *font_info
1310 = FONT_INFO_FROM_ID (f, face->font_info_id);
1311 if (font_info)
1312 x_encode_char (c, char2b, font_info);
1316 /* Make sure X resources of the face are allocated. */
1317 xassert (face != NULL);
1318 PREPARE_FACE_FOR_DISPLAY (f, face);
1320 return face;
1324 /* Determine if a font is double byte. */
1325 int w32_font_is_double_byte (XFontStruct *font)
1327 /* NTEMACS_TODO: Determine this properly using GetFontLanguageInfo
1328 or similar. Returning 1 might work, as we use Unicode anyway. */
1329 return 1;
1333 /* Get face and two-byte form of character glyph GLYPH on frame F.
1334 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1335 a pointer to a realized face that is ready for display. */
1337 static INLINE struct face *
1338 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1339 struct frame *f;
1340 struct glyph *glyph;
1341 wchar_t *char2b;
1342 int *two_byte_p;
1344 struct face *face;
1346 xassert (glyph->type == CHAR_GLYPH);
1347 face = FACE_FROM_ID (f, glyph->face_id);
1349 if (two_byte_p)
1350 *two_byte_p = 0;
1352 if (!glyph->multibyte_p)
1354 /* Unibyte case. We don't have to encode, but we have to make
1355 sure to use a face suitable for unibyte. */
1356 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1358 else if (glyph->u.ch < 128
1359 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1361 /* Case of ASCII in a face known to fit ASCII. */
1362 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1364 else
1366 int c1, c2, charset;
1368 /* Split characters into bytes. If c2 is -1 afterwards, C is
1369 really a one-byte character so that byte1 is zero. */
1370 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1371 if (c2 > 0)
1372 *char2b = BUILD_WCHAR_T (c1, c2);
1373 else
1374 *char2b = BUILD_WCHAR_T (0, c1);
1376 /* Maybe encode the character in *CHAR2B. */
1377 if (charset != CHARSET_ASCII)
1379 struct font_info *font_info
1380 = FONT_INFO_FROM_ID (f, face->font_info_id);
1381 if (font_info)
1383 x_encode_char (glyph->u.ch, char2b, font_info);
1384 if (two_byte_p)
1385 *two_byte_p = w32_font_is_double_byte (font_info->font);
1390 /* Make sure X resources of the face are allocated. */
1391 xassert (face != NULL);
1392 PREPARE_FACE_FOR_DISPLAY (f, face);
1393 return face;
1397 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1398 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1400 static INLINE void
1401 x_append_glyph (it)
1402 struct it *it;
1404 struct glyph *glyph;
1405 enum glyph_row_area area = it->area;
1407 xassert (it->glyph_row);
1408 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1410 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1411 if (glyph < it->glyph_row->glyphs[area + 1])
1413 /* Play it safe. If sub-structures of the glyph are not all the
1414 same size, it otherwise be that some bits stay set. This
1415 would prevent a comparison with GLYPH_EQUAL_P. */
1416 glyph->u.val = 0;
1418 glyph->type = CHAR_GLYPH;
1419 glyph->pixel_width = it->pixel_width;
1420 glyph->u.ch = it->char_to_display;
1421 glyph->face_id = it->face_id;
1422 glyph->charpos = CHARPOS (it->position);
1423 glyph->object = it->object;
1424 glyph->left_box_line_p = it->start_of_box_run_p;
1425 glyph->right_box_line_p = it->end_of_box_run_p;
1426 glyph->voffset = it->voffset;
1427 glyph->multibyte_p = it->multibyte_p;
1428 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1429 || it->phys_descent > it->descent);
1430 glyph->glyph_not_available_p = it->glyph_not_available_p;
1431 ++it->glyph_row->used[area];
1435 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1436 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1438 static INLINE void
1439 x_append_composite_glyph (it)
1440 struct it *it;
1442 struct glyph *glyph;
1443 enum glyph_row_area area = it->area;
1445 xassert (it->glyph_row);
1447 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1448 if (glyph < it->glyph_row->glyphs[area + 1])
1450 /* Play it safe. If sub-structures of the glyph are not all the
1451 same size, it otherwise be that some bits stay set. This
1452 would prevent a comparison with GLYPH_EQUAL_P. */
1453 glyph->u.val = 0;
1455 glyph->type = COMPOSITE_GLYPH;
1456 glyph->pixel_width = it->pixel_width;
1457 glyph->u.cmp_id = it->cmp_id;
1458 glyph->face_id = it->face_id;
1459 glyph->charpos = CHARPOS (it->position);
1460 glyph->object = it->object;
1461 glyph->left_box_line_p = it->start_of_box_run_p;
1462 glyph->right_box_line_p = it->end_of_box_run_p;
1463 glyph->voffset = it->voffset;
1464 glyph->multibyte_p = it->multibyte_p;
1465 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1466 || it->phys_descent > it->descent);
1467 ++it->glyph_row->used[area];
1472 /* Change IT->ascent and IT->height according to the setting of
1473 IT->voffset. */
1475 static INLINE void
1476 take_vertical_position_into_account (it)
1477 struct it *it;
1479 if (it->voffset)
1481 if (it->voffset < 0)
1482 /* Increase the ascent so that we can display the text higher
1483 in the line. */
1484 it->ascent += abs (it->voffset);
1485 else
1486 /* Increase the descent so that we can display the text lower
1487 in the line. */
1488 it->descent += it->voffset;
1493 /* Produce glyphs/get display metrics for the image IT is loaded with.
1494 See the description of struct display_iterator in dispextern.h for
1495 an overview of struct display_iterator. */
1497 static void
1498 x_produce_image_glyph (it)
1499 struct it *it;
1501 struct image *img;
1502 struct face *face;
1504 xassert (it->what == IT_IMAGE);
1506 face = FACE_FROM_ID (it->f, it->face_id);
1507 img = IMAGE_FROM_ID (it->f, it->image_id);
1508 xassert (img);
1510 /* Make sure X resources of the face and image are loaded. */
1511 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1512 prepare_image_for_display (it->f, img);
1514 it->ascent = it->phys_ascent = IMAGE_ASCENT (img);
1515 it->descent = it->phys_descent = img->height + 2 * img->margin - it->ascent;
1516 it->pixel_width = img->width + 2 * img->margin;
1518 it->nglyphs = 1;
1520 if (face->box != FACE_NO_BOX)
1522 it->ascent += face->box_line_width;
1523 it->descent += face->box_line_width;
1525 if (it->start_of_box_run_p)
1526 it->pixel_width += face->box_line_width;
1527 if (it->end_of_box_run_p)
1528 it->pixel_width += face->box_line_width;
1531 take_vertical_position_into_account (it);
1533 if (it->glyph_row)
1535 struct glyph *glyph;
1536 enum glyph_row_area area = it->area;
1538 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1539 if (glyph < it->glyph_row->glyphs[area + 1])
1541 glyph->type = IMAGE_GLYPH;
1542 glyph->u.img_id = img->id;
1543 glyph->face_id = it->face_id;
1544 glyph->pixel_width = it->pixel_width;
1545 glyph->charpos = CHARPOS (it->position);
1546 glyph->object = it->object;
1547 glyph->left_box_line_p = it->start_of_box_run_p;
1548 glyph->right_box_line_p = it->end_of_box_run_p;
1549 glyph->voffset = it->voffset;
1550 glyph->multibyte_p = it->multibyte_p;
1551 ++it->glyph_row->used[area];
1557 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1558 of the glyph, WIDTH and HEIGHT are the width and height of the
1559 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1560 ascent of the glyph (0 <= ASCENT <= 1). */
1562 static void
1563 x_append_stretch_glyph (it, object, width, height, ascent)
1564 struct it *it;
1565 Lisp_Object object;
1566 int width, height;
1567 double ascent;
1569 struct glyph *glyph;
1570 enum glyph_row_area area = it->area;
1572 xassert (ascent >= 0 && ascent <= 1);
1574 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1575 if (glyph < it->glyph_row->glyphs[area + 1])
1577 glyph->type = STRETCH_GLYPH;
1578 glyph->u.stretch.ascent = height * ascent;
1579 glyph->u.stretch.height = height;
1580 glyph->face_id = it->face_id;
1581 glyph->pixel_width = width;
1582 glyph->charpos = CHARPOS (it->position);
1583 glyph->object = object;
1584 glyph->left_box_line_p = it->start_of_box_run_p;
1585 glyph->right_box_line_p = it->end_of_box_run_p;
1586 glyph->voffset = it->voffset;
1587 glyph->multibyte_p = it->multibyte_p;
1588 ++it->glyph_row->used[area];
1593 /* Produce a stretch glyph for iterator IT. IT->object is the value
1594 of the glyph property displayed. The value must be a list
1595 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1596 being recognized:
1598 1. `:width WIDTH' specifies that the space should be WIDTH *
1599 canonical char width wide. WIDTH may be an integer or floating
1600 point number.
1602 2. `:relative-width FACTOR' specifies that the width of the stretch
1603 should be computed from the width of the first character having the
1604 `glyph' property, and should be FACTOR times that width.
1606 3. `:align-to HPOS' specifies that the space should be wide enough
1607 to reach HPOS, a value in canonical character units.
1609 Exactly one of the above pairs must be present.
1611 4. `:height HEIGHT' specifies that the height of the stretch produced
1612 should be HEIGHT, measured in canonical character units.
1614 5. `:relative-height FACTOR' specifies that the height of the the
1615 stretch should be FACTOR times the height of the characters having
1616 the glyph property.
1618 Either none or exactly one of 4 or 5 must be present.
1620 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1621 of the stretch should be used for the ascent of the stretch.
1622 ASCENT must be in the range 0 <= ASCENT <= 100. */
1624 #define NUMVAL(X) \
1625 ((INTEGERP (X) || FLOATP (X)) \
1626 ? XFLOATINT (X) \
1627 : - 1)
1630 static void
1631 x_produce_stretch_glyph (it)
1632 struct it *it;
1634 /* (space :width WIDTH :height HEIGHT. */
1635 extern Lisp_Object QCwidth, QCheight, QCascent, Qspace;
1636 extern Lisp_Object QCrelative_width, QCrelative_height;
1637 extern Lisp_Object QCalign_to;
1638 Lisp_Object prop, plist;
1639 double width = 0, height = 0, ascent = 0;
1640 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1641 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1643 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1645 /* List should start with `space'. */
1646 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1647 plist = XCDR (it->object);
1649 /* Compute the width of the stretch. */
1650 if (prop = Fplist_get (plist, QCwidth),
1651 NUMVAL (prop) > 0)
1652 /* Absolute width `:width WIDTH' specified and valid. */
1653 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1654 else if (prop = Fplist_get (plist, QCrelative_width),
1655 NUMVAL (prop) > 0)
1657 /* Relative width `:relative-width FACTOR' specified and valid.
1658 Compute the width of the characters having the `glyph'
1659 property. */
1660 struct it it2;
1661 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1663 it2 = *it;
1664 if (it->multibyte_p)
1666 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1667 - IT_BYTEPOS (*it));
1668 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1670 else
1671 it2.c = *p, it2.len = 1;
1673 it2.glyph_row = NULL;
1674 it2.what = IT_CHARACTER;
1675 x_produce_glyphs (&it2);
1676 width = NUMVAL (prop) * it2.pixel_width;
1678 else if (prop = Fplist_get (plist, QCalign_to),
1679 NUMVAL (prop) > 0)
1680 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1681 else
1682 /* Nothing specified -> width defaults to canonical char width. */
1683 width = CANON_X_UNIT (it->f);
1685 /* Compute height. */
1686 if (prop = Fplist_get (plist, QCheight),
1687 NUMVAL (prop) > 0)
1688 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1689 else if (prop = Fplist_get (plist, QCrelative_height),
1690 NUMVAL (prop) > 0)
1691 height = FONT_HEIGHT (font) * NUMVAL (prop);
1692 else
1693 height = FONT_HEIGHT (font);
1695 /* Compute percentage of height used for ascent. If
1696 `:ascent ASCENT' is present and valid, use that. Otherwise,
1697 derive the ascent from the font in use. */
1698 if (prop = Fplist_get (plist, QCascent),
1699 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1700 ascent = NUMVAL (prop) / 100.0;
1701 else
1702 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1704 if (width <= 0)
1705 width = 1;
1706 if (height <= 0)
1707 height = 1;
1709 if (it->glyph_row)
1711 Lisp_Object object = it->stack[it->sp - 1].string;
1712 if (!STRINGP (object))
1713 object = it->w->buffer;
1714 x_append_stretch_glyph (it, object, width, height, ascent);
1717 it->pixel_width = width;
1718 it->ascent = it->phys_ascent = height * ascent;
1719 it->descent = it->phys_descent = height - it->ascent;
1720 it->nglyphs = 1;
1722 if (face->box != FACE_NO_BOX)
1724 it->ascent += face->box_line_width;
1725 it->descent += face->box_line_width;
1727 if (it->start_of_box_run_p)
1728 it->pixel_width += face->box_line_width;
1729 if (it->end_of_box_run_p)
1730 it->pixel_width += face->box_line_width;
1733 take_vertical_position_into_account (it);
1736 /* Return proper value to be used as baseline offset of font that has
1737 ASCENT and DESCENT to draw characters by the font at the vertical
1738 center of the line of frame F.
1740 Here, out task is to find the value of BOFF in the following figure;
1742 -------------------------+-----------+-
1743 -+-+---------+-+ | |
1744 | | | | | |
1745 | | | | F_ASCENT F_HEIGHT
1746 | | | ASCENT | |
1747 HEIGHT | | | | |
1748 | | |-|-+------+-----------|------- baseline
1749 | | | | BOFF | |
1750 | |---------|-+-+ | |
1751 | | | DESCENT | |
1752 -+-+---------+-+ F_DESCENT |
1753 -------------------------+-----------+-
1755 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1756 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1757 DESCENT = FONT->descent
1758 HEIGHT = FONT_HEIGHT (FONT)
1759 F_DESCENT = (F->output_data.x->font->descent
1760 - F->output_data.x->baseline_offset)
1761 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1764 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1765 (FONT_DESCENT (FONT) \
1766 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT))) / 2 \
1767 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1769 /* Produce glyphs/get display metrics for the display element IT is
1770 loaded with. See the description of struct display_iterator in
1771 dispextern.h for an overview of struct display_iterator. */
1773 static void
1774 x_produce_glyphs (it)
1775 struct it *it;
1777 it->glyph_not_available_p = 0;
1779 if (it->what == IT_CHARACTER)
1781 wchar_t char2b;
1782 XFontStruct *font;
1783 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1784 XCharStruct *pcm;
1785 int font_not_found_p;
1786 struct font_info *font_info;
1787 int boff; /* baseline offset */
1788 HDC hdc;
1790 hdc = get_frame_dc (it->f);
1792 /* Maybe translate single-byte characters to multibyte, or the
1793 other way. */
1794 it->char_to_display = it->c;
1795 if (!ASCII_BYTE_P (it->c))
1797 if (unibyte_display_via_language_environment
1798 && SINGLE_BYTE_CHAR_P (it->c)
1799 && (it->c >= 0240
1800 || !NILP (Vnonascii_translation_table)))
1802 it->char_to_display = unibyte_char_to_multibyte (it->c);
1803 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1804 face = FACE_FROM_ID (it->f, it->face_id);
1806 else if (!SINGLE_BYTE_CHAR_P (it->c)
1807 && !it->multibyte_p)
1809 it->char_to_display = multibyte_char_to_unibyte (it->c, Qnil);
1810 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
1811 face = FACE_FROM_ID (it->f, it->face_id);
1815 /* Get font to use. Encode IT->char_to_display. */
1816 x_get_char_face_and_encoding (it->f, it->char_to_display,
1817 it->face_id, &char2b,
1818 it->multibyte_p);
1819 font = face->font;
1821 /* When no suitable font found, use the default font. */
1822 font_not_found_p = font == NULL;
1823 if (font_not_found_p)
1825 font = FRAME_FONT (it->f);
1826 boff = it->f->output_data.w32->baseline_offset;
1827 font_info = NULL;
1829 else
1831 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
1832 boff = font_info->baseline_offset;
1833 if (font_info->vertical_centering)
1834 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
1837 if (font->hfont)
1838 SelectObject (hdc, font->hfont);
1840 if (it->char_to_display >= ' '
1841 && (!it->multibyte_p || it->char_to_display < 128))
1843 /* Either unibyte or ASCII. */
1844 int stretched_p;
1846 it->nglyphs = 1;
1848 pcm = w32_per_char_metric (hdc, font, &char2b, 0);
1849 it->ascent = FONT_BASE (font) + boff;
1850 it->descent = FONT_DESCENT (font) - boff;
1851 it->phys_ascent = pcm->ascent + boff;
1852 it->phys_descent = pcm->descent - boff;
1853 it->pixel_width = pcm->width;
1855 /* If this is a space inside a region of text with
1856 `space-width' property, change its width. */
1857 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
1858 if (stretched_p)
1859 it->pixel_width *= XFLOATINT (it->space_width);
1861 /* If face has a box, add the box thickness to the character
1862 height. If character has a box line to the left and/or
1863 right, add the box line width to the character's width. */
1864 if (face->box != FACE_NO_BOX)
1866 int thick = face->box_line_width;
1868 it->ascent += thick;
1869 it->descent += thick;
1871 if (it->start_of_box_run_p)
1872 it->pixel_width += thick;
1873 if (it->end_of_box_run_p)
1874 it->pixel_width += thick;
1877 /* If face has an overline, add the height of the overline
1878 (1 pixel) and a 1 pixel margin to the character height. */
1879 if (face->overline_p)
1880 it->ascent += 2;
1882 take_vertical_position_into_account (it);
1884 /* If we have to actually produce glyphs, do it. */
1885 if (it->glyph_row)
1887 if (stretched_p)
1889 /* Translate a space with a `space-width' property
1890 into a stretch glyph. */
1891 double ascent = (double) FONT_BASE (font)
1892 / FONT_HEIGHT (font);
1893 x_append_stretch_glyph (it, it->object, it->pixel_width,
1894 it->ascent + it->descent, ascent);
1896 else
1897 x_append_glyph (it);
1899 /* If characters with lbearing or rbearing are displayed
1900 in this line, record that fact in a flag of the
1901 glyph row. This is used to optimize X output code. */
1902 if (pcm->lbearing < 0
1903 || pcm->rbearing > pcm->width)
1904 it->glyph_row->contains_overlapping_glyphs_p = 1;
1905 xfree (pcm);
1908 else if (it->char_to_display == '\n')
1910 /* A newline has no width but we need the height of the line. */
1911 it->pixel_width = 0;
1912 it->nglyphs = 0;
1913 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
1914 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1916 if (face->box != FACE_NO_BOX)
1918 int thick = face->box_line_width;
1919 it->ascent += thick;
1920 it->descent += thick;
1923 else if (it->char_to_display == '\t')
1925 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
1926 int x = (it->current_x
1927 - it->prompt_width
1928 + it->continuation_lines_width);
1929 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
1931 it->pixel_width = next_tab_x - x;
1932 it->nglyphs = 1;
1933 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
1934 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
1936 if (it->glyph_row)
1938 double ascent = (double) it->ascent / (it->ascent + it->descent);
1939 x_append_stretch_glyph (it, it->object, it->pixel_width,
1940 it->ascent + it->descent, ascent);
1943 else
1945 /* A multi-byte character.
1946 If we found a font, this font should give us the right
1947 metrics. If we didn't find a font, use the frame's
1948 default font and calculate the width of the character
1949 from the charset width; this is what old redisplay code
1950 did. */
1951 pcm = w32_per_char_metric (hdc, font, &char2b, 1);
1953 if (font_not_found_p || !pcm)
1955 int charset = CHAR_CHARSET (it->char_to_display);
1957 it->glyph_not_available_p = 1;
1958 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
1959 * CHARSET_WIDTH (charset));
1960 it->phys_ascent = FONT_BASE (font) + boff;
1961 it->phys_descent = FONT_DESCENT (font) - boff;
1963 else
1965 it->phys_ascent = pcm->ascent + boff;
1966 it->phys_descent = pcm->descent - boff;
1967 if (it->glyph_row
1968 && (pcm->lbearing < 0
1969 || pcm->rbearing > pcm->width))
1970 it->glyph_row->contains_overlapping_glyphs_p = 1;
1973 it->nglyphs = 1;
1974 it->ascent = FONT_BASE (font) + boff;
1975 it->descent = FONT_DESCENT (font) - boff;
1977 if (face->box != FACE_NO_BOX)
1979 int thick = face->box_line_width;
1980 it->ascent += thick;
1981 it->descent += thick;
1983 if (it->start_of_box_run_p)
1984 it->pixel_width += thick;
1985 if (it->end_of_box_run_p)
1986 it->pixel_width += thick;
1989 /* If face has an overline, add the height of the overline
1990 (1 pixel) and a 1 pixel margin to the character height. */
1991 if (face->overline_p)
1992 it->ascent += 2;
1994 take_vertical_position_into_account (it);
1996 if (it->glyph_row)
1997 x_append_glyph (it);
1999 xfree (pcm);
2001 release_frame_dc (it->f, hdc);
2003 else if (it->what == IT_COMPOSITION)
2005 /* NTEMACS_TODO: Composite glyphs. */
2007 else if (it->what == IT_IMAGE)
2008 x_produce_image_glyph (it);
2009 else if (it->what == IT_STRETCH)
2010 x_produce_stretch_glyph (it);
2012 /* Accumulate dimensions. */
2013 xassert (it->ascent >= 0 && it->descent > 0);
2014 if (it->area == TEXT_AREA)
2015 it->current_x += it->pixel_width;
2017 it->max_ascent = max (it->max_ascent, it->ascent);
2018 it->max_descent = max (it->max_descent, it->descent);
2019 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2020 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2024 /* Estimate the pixel height of the mode or top line on frame F.
2025 FACE_ID specifies what line's height to estimate. */
2028 x_estimate_mode_line_height (f, face_id)
2029 struct frame *f;
2030 enum face_id face_id;
2032 int height = 1;
2034 /* This function is called so early when Emacs starts that the face
2035 cache and mode line face are not yet initialized. */
2036 if (FRAME_FACE_CACHE (f))
2038 struct face *face = FACE_FROM_ID (f, face_id);
2039 if (face && face->font)
2040 height = FONT_HEIGHT (face->font) + 2 * face->box_line_width;
2043 return height;
2047 /* Get the Windows codepage corresponding to the specified font. The
2048 charset info in the font name is used to look up
2049 w32-charset-to-codepage-alist. */
2050 int
2051 w32_codepage_for_font (char *fontname)
2053 Lisp_Object codepage;
2054 char charset_str[20], *charset, *end;
2056 /* Extract charset part of font string. */
2057 if (sscanf (fontname,
2058 "-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%19s",
2059 charset_str) == EOF)
2060 return CP_DEFAULT;
2062 /* Remove leading "*-". */
2063 if (strncmp ("*-", charset_str, 2) == 0)
2064 charset = charset_str + 2;
2065 else
2066 charset = charset_str;
2068 /* Stop match at wildcard (including preceding '-'). */
2069 if (end = strchr (charset, '*'))
2071 if (end > charset && *(end-1) == '-')
2072 end--;
2073 *end = '\0';
2076 codepage = Fcdr (Fcdr (Fassoc (build_string(charset),
2077 Vw32_charset_info_alist)));
2078 if (INTEGERP (codepage))
2079 return XINT (codepage);
2080 else
2081 return CP_DEFAULT;
2084 BOOL
2085 w32_use_unicode_for_codepage (codepage)
2086 int codepage;
2088 /* If the current codepage is supported, use Unicode for output. */
2089 return (w32_enable_unicode_output
2090 && codepage != CP_DEFAULT && IsValidCodePage (codepage));
2094 /***********************************************************************
2095 Glyph display
2096 ***********************************************************************/
2098 /* A sequence of glyphs to be drawn in the same face.
2100 This data structure is not really completely X specific, so it
2101 could possibly, at least partially, be useful for other systems. It
2102 is currently not part of the external redisplay interface because
2103 it's not clear what other systems will need. */
2105 struct glyph_string
2107 /* X-origin of the string. */
2108 int x;
2110 /* Y-origin and y-position of the base line of this string. */
2111 int y, ybase;
2113 /* The width of the string, not including a face extension. */
2114 int width;
2116 /* The width of the string, including a face extension. */
2117 int background_width;
2119 /* The height of this string. This is the height of the line this
2120 string is drawn in, and can be different from the height of the
2121 font the string is drawn in. */
2122 int height;
2124 /* Number of pixels this string overwrites in front of its x-origin.
2125 This number is zero if the string has an lbearing >= 0; it is
2126 -lbearing, if the string has an lbearing < 0. */
2127 int left_overhang;
2129 /* Number of pixels this string overwrites past its right-most
2130 nominal x-position, i.e. x + width. Zero if the string's
2131 rbearing is <= its nominal width, rbearing - width otherwise. */
2132 int right_overhang;
2134 /* The frame on which the glyph string is drawn. */
2135 struct frame *f;
2137 /* The window on which the glyph string is drawn. */
2138 struct window *w;
2140 /* X display and window for convenience. */
2141 Window window;
2143 /* The glyph row for which this string was built. It determines the
2144 y-origin and height of the string. */
2145 struct glyph_row *row;
2147 /* The area within row. */
2148 enum glyph_row_area area;
2150 /* Characters to be drawn, and number of characters. */
2151 wchar_t *char2b;
2152 int nchars;
2154 /* A face-override for drawing cursors, mouse face and similar. */
2155 enum draw_glyphs_face hl;
2157 /* Face in which this string is to be drawn. */
2158 struct face *face;
2160 /* Font in which this string is to be drawn. */
2161 XFontStruct *font;
2163 /* Font info for this string. */
2164 struct font_info *font_info;
2166 /* Non-null means this string describes (part of) a composition.
2167 All characters from char2b are drawn composed. */
2168 struct composition *cmp;
2170 /* Index of this glyph string's first character in the glyph
2171 definition of CMP. If this is zero, this glyph string describes
2172 the first character of a composition. */
2173 int gidx;
2175 /* 1 means this glyph strings face has to be drawn to the right end
2176 of the window's drawing area. */
2177 unsigned extends_to_end_of_line_p : 1;
2179 /* 1 means the background of this string has been drawn. */
2180 unsigned background_filled_p : 1;
2182 /* 1 means glyph string must be drawn with 16-bit functions. */
2183 unsigned two_byte_p : 1;
2185 /* 1 means that the original font determined for drawing this glyph
2186 string could not be loaded. The member `font' has been set to
2187 the frame's default font in this case. */
2188 unsigned font_not_found_p : 1;
2190 /* 1 means that the face in which this glyph string is drawn has a
2191 stipple pattern. */
2192 unsigned stippled_p : 1;
2194 /* 1 means only the foreground of this glyph string must be drawn,
2195 and we should use the physical height of the line this glyph
2196 string appears in as clip rect. */
2197 unsigned for_overlaps_p : 1;
2199 /* The GC to use for drawing this glyph string. */
2200 XGCValues *gc;
2202 HDC hdc;
2204 /* A pointer to the first glyph in the string. This glyph
2205 corresponds to char2b[0]. Needed to draw rectangles if
2206 font_not_found_p is 1. */
2207 struct glyph *first_glyph;
2209 /* Image, if any. */
2210 struct image *img;
2212 struct glyph_string *next, *prev;
2216 /* Encapsulate the different ways of printing text under W32. */
2218 void W32_TEXTOUT(s, x, y,chars,nchars)
2219 struct glyph_string * s;
2220 int x, y;
2221 wchar_t * chars;
2222 int nchars;
2224 /* NTEMACS_TODO: Find way to figure out charset_dim. */
2225 /* int charset_dim = CHARSET_DIMENSION (s->charset); */
2226 if (s->gc->font->bdf)
2227 w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
2228 x, y, (char *) chars, 1 /* charset_dim */, nchars, 0);
2229 else if (s->two_byte_p)
2230 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
2231 else
2232 ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
2233 nchars /* * charset_dim */, NULL);
2236 #if 0
2238 static void
2239 x_dump_glyph_string (s)
2240 struct glyph_string *s;
2242 fprintf (stderr, "glyph string\n");
2243 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2244 s->x, s->y, s->width, s->height);
2245 fprintf (stderr, " ybase = %d\n", s->ybase);
2246 fprintf (stderr, " hl = %d\n", s->hl);
2247 fprintf (stderr, " left overhang = %d, right = %d\n",
2248 s->left_overhang, s->right_overhang);
2249 fprintf (stderr, " nchars = %d\n", s->nchars);
2250 fprintf (stderr, " extends to end of line = %d\n",
2251 s->extends_to_end_of_line_p);
2252 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2253 fprintf (stderr, " bg width = %d\n", s->background_width);
2256 #endif /* GLYPH_DEBUG */
2260 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2261 struct glyph_string **,
2262 struct glyph_string *,
2263 struct glyph_string *));
2264 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2265 struct glyph_string **,
2266 struct glyph_string *,
2267 struct glyph_string *));
2268 static void x_append_glyph_string P_ ((struct glyph_string **,
2269 struct glyph_string **,
2270 struct glyph_string *));
2271 static int x_left_overwritten P_ ((struct glyph_string *));
2272 static int x_left_overwriting P_ ((struct glyph_string *));
2273 static int x_right_overwritten P_ ((struct glyph_string *));
2274 static int x_right_overwriting P_ ((struct glyph_string *));
2275 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int,
2276 int, int));
2277 static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
2278 wchar_t *, struct window *,
2279 struct glyph_row *,
2280 enum glyph_row_area, int,
2281 enum draw_glyphs_face));
2282 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2283 enum glyph_row_area, int, int,
2284 enum draw_glyphs_face, int *, int *, int));
2285 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2286 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2287 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2288 int));
2289 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2290 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2291 static void x_draw_glyph_string_underline P_ ((struct glyph_string *));
2292 static void x_draw_glyph_string_underline P_ ((struct glyph_string *));
2293 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2294 static void x_draw_glyph_string P_ ((struct glyph_string *));
2295 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2296 static void x_set_cursor_gc P_ ((struct glyph_string *));
2297 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2298 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2299 static void w32_get_glyph_overhangs P_ ((HDC hdc, struct glyph *,
2300 struct frame *,
2301 int *, int *, int));
2302 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2303 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
2304 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
2305 double, int, COLORREF));
2306 static void x_setup_relief_colors P_ ((struct glyph_string *));
2307 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2308 static void x_draw_image_relief P_ ((struct glyph_string *));
2309 static void x_draw_image_foreground P_ ((struct glyph_string *));
2310 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
2311 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2312 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2313 int, int, int));
2314 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2315 int, int, int, int, RECT *));
2316 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2317 int, int, int, RECT *));
2318 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2319 enum glyph_row_area));
2322 /* Append the list of glyph strings with head H and tail T to the list
2323 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2325 static INLINE void
2326 x_append_glyph_string_lists (head, tail, h, t)
2327 struct glyph_string **head, **tail;
2328 struct glyph_string *h, *t;
2330 if (h)
2332 if (*head)
2333 (*tail)->next = h;
2334 else
2335 *head = h;
2336 h->prev = *tail;
2337 *tail = t;
2342 /* Prepend the list of glyph strings with head H and tail T to the
2343 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2344 result. */
2346 static INLINE void
2347 x_prepend_glyph_string_lists (head, tail, h, t)
2348 struct glyph_string **head, **tail;
2349 struct glyph_string *h, *t;
2351 if (h)
2353 if (*head)
2354 (*head)->prev = t;
2355 else
2356 *tail = t;
2357 t->next = *head;
2358 *head = h;
2363 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2364 Set *HEAD and *TAIL to the resulting list. */
2366 static INLINE void
2367 x_append_glyph_string (head, tail, s)
2368 struct glyph_string **head, **tail;
2369 struct glyph_string *s;
2371 s->next = s->prev = NULL;
2372 x_append_glyph_string_lists (head, tail, s, s);
2376 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2377 face. */
2379 static void
2380 x_set_cursor_gc (s)
2381 struct glyph_string *s;
2383 if (s->font == FRAME_FONT (s->f)
2384 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2385 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2386 && !s->cmp)
2387 s->gc = s->f->output_data.w32->cursor_gc;
2388 else
2390 /* Cursor on non-default face: must merge. */
2391 XGCValues xgcv;
2392 unsigned long mask;
2394 xgcv.background = s->f->output_data.w32->cursor_pixel;
2395 xgcv.foreground = s->face->background;
2397 /* If the glyph would be invisible, try a different foreground. */
2398 if (xgcv.foreground == xgcv.background)
2399 xgcv.foreground = s->face->foreground;
2400 if (xgcv.foreground == xgcv.background)
2401 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
2402 if (xgcv.foreground == xgcv.background)
2403 xgcv.foreground = s->face->foreground;
2405 /* Make sure the cursor is distinct from text in this face. */
2406 if (xgcv.background == s->face->background
2407 && xgcv.foreground == s->face->foreground)
2409 xgcv.background = s->face->foreground;
2410 xgcv.foreground = s->face->background;
2413 IF_DEBUG (x_check_font (s->f, s->font));
2414 xgcv.font = s->font;
2415 mask = GCForeground | GCBackground | GCFont;
2417 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2418 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2419 mask, &xgcv);
2420 else
2421 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2422 = XCreateGC (NULL, s->window, mask, &xgcv);
2424 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2429 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2431 static void
2432 x_set_mouse_face_gc (s)
2433 struct glyph_string *s;
2435 int face_id;
2436 struct face *face;
2438 /* What face has to be used for the mouse face? */
2439 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
2440 face = FACE_FROM_ID (s->f, face_id);
2441 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2442 s->face = FACE_FROM_ID (s->f, face_id);
2443 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2445 /* If font in this face is same as S->font, use it. */
2446 if (s->font == s->face->font)
2447 s->gc = s->face->gc;
2448 else
2450 /* Otherwise construct scratch_cursor_gc with values from FACE
2451 but font FONT. */
2452 XGCValues xgcv;
2453 unsigned long mask;
2455 xgcv.background = s->face->background;
2456 xgcv.foreground = s->face->foreground;
2457 IF_DEBUG (x_check_font (s->f, s->font));
2458 xgcv.font = s->font;
2459 mask = GCForeground | GCBackground | GCFont;
2461 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2462 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2463 mask, &xgcv);
2464 else
2465 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2466 = XCreateGC (NULL, s->window, mask, &xgcv);
2468 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2471 xassert (s->gc != 0);
2475 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2476 Faces to use in the mode line have already been computed when the
2477 matrix was built, so there isn't much to do, here. */
2479 static INLINE void
2480 x_set_mode_line_face_gc (s)
2481 struct glyph_string *s;
2483 s->gc = s->face->gc;
2484 xassert (s->gc != 0);
2488 /* Set S->gc of glyph string S for drawing that glyph string. Set
2489 S->stippled_p to a non-zero value if the face of S has a stipple
2490 pattern. */
2492 static INLINE void
2493 x_set_glyph_string_gc (s)
2494 struct glyph_string *s;
2496 if (s->hl == DRAW_NORMAL_TEXT)
2498 s->gc = s->face->gc;
2499 s->stippled_p = s->face->stipple != 0;
2501 else if (s->hl == DRAW_INVERSE_VIDEO)
2503 x_set_mode_line_face_gc (s);
2504 s->stippled_p = s->face->stipple != 0;
2506 else if (s->hl == DRAW_CURSOR)
2508 x_set_cursor_gc (s);
2509 s->stippled_p = 0;
2511 else if (s->hl == DRAW_MOUSE_FACE)
2513 x_set_mouse_face_gc (s);
2514 s->stippled_p = s->face->stipple != 0;
2516 else if (s->hl == DRAW_IMAGE_RAISED
2517 || s->hl == DRAW_IMAGE_SUNKEN)
2519 s->gc = s->face->gc;
2520 s->stippled_p = s->face->stipple != 0;
2522 else
2524 s->gc = s->face->gc;
2525 s->stippled_p = s->face->stipple != 0;
2528 /* GC must have been set. */
2529 xassert (s->gc != 0);
2533 /* Return in *R the clipping rectangle for glyph string S. */
2535 static void
2536 w32_get_glyph_string_clip_rect (s, r)
2537 struct glyph_string *s;
2538 RECT *r;
2540 int r_height, r_width;
2542 if (s->row->full_width_p)
2544 /* Draw full-width. X coordinates are relative to S->w->left. */
2545 int canon_x = CANON_X_UNIT (s->f);
2547 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
2548 r_width = XFASTINT (s->w->width) * canon_x;
2550 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
2552 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
2553 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
2554 r->left -= width;
2557 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
2559 /* Unless displaying a mode or menu bar line, which are always
2560 fully visible, clip to the visible part of the row. */
2561 if (s->w->pseudo_window_p)
2562 r_height = s->row->visible_height;
2563 else
2564 r_height = s->height;
2566 else
2568 /* This is a text line that may be partially visible. */
2569 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
2570 r_width = window_box_width (s->w, s->area);
2571 r_height = s->row->visible_height;
2574 /* Don't use S->y for clipping because it doesn't take partially
2575 visible lines into account. For example, it can be negative for
2576 partially visible lines at the top of a window. */
2577 if (!s->row->full_width_p
2578 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
2579 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2580 else
2581 r->top = max (0, s->row->y);
2583 /* If drawing a tool-bar window, draw it over the internal border
2584 at the top of the window. */
2585 if (s->w == XWINDOW (s->f->tool_bar_window))
2586 r->top -= s->f->output_data.w32->internal_border_width;
2588 /* If S draws overlapping rows, it's sufficient to use the top and
2589 bottom of the window for clipping because this glyph string
2590 intentionally draws over other lines. */
2591 if (s->for_overlaps_p)
2593 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
2594 r_height = window_text_bottom_y (s->w) - r->top;
2597 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
2599 r->bottom = r->top + r_height;
2600 r->right = r->left + r_width;
2604 /* Set clipping for output of glyph string S. S may be part of a mode
2605 line or menu if we don't have X toolkit support. */
2607 static INLINE void
2608 x_set_glyph_string_clipping (s)
2609 struct glyph_string *s;
2611 RECT r;
2612 w32_get_glyph_string_clip_rect (s, &r);
2613 w32_set_clip_rectangle (s->hdc, &r);
2617 /* Compute left and right overhang of glyph string S. If S is a glyph
2618 string for a composition, assume overhangs don't exist. */
2620 static INLINE void
2621 x_compute_glyph_string_overhangs (s)
2622 struct glyph_string *s;
2624 if (s->cmp == NULL
2625 && s->first_glyph->type == CHAR_GLYPH)
2627 XCharStruct cs;
2628 int direction, font_ascent, font_descent;
2629 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2630 &font_ascent, &font_descent, &cs);
2631 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2632 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2637 /* Compute overhangs and x-positions for glyph string S and its
2638 predecessors, or successors. X is the starting x-position for S.
2639 BACKWARD_P non-zero means process predecessors. */
2641 static void
2642 x_compute_overhangs_and_x (s, x, backward_p)
2643 struct glyph_string *s;
2644 int x;
2645 int backward_p;
2647 if (backward_p)
2649 while (s)
2651 x_compute_glyph_string_overhangs (s);
2652 x -= s->width;
2653 s->x = x;
2654 s = s->prev;
2657 else
2659 while (s)
2661 x_compute_glyph_string_overhangs (s);
2662 s->x = x;
2663 x += s->width;
2664 s = s->next;
2670 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
2671 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
2672 assumed to be zero. */
2674 static void
2675 w32_get_glyph_overhangs (hdc, glyph, f, left, right, unicode_p)
2676 HDC hdc;
2677 struct glyph *glyph;
2678 struct frame *f;
2679 int *left, *right, unicode_p;
2681 int c;
2683 *left = *right = 0;
2685 if (glyph->type == CHAR_GLYPH)
2687 XFontStruct *font;
2688 struct face *face;
2689 struct font_info *font_info;
2690 wchar_t char2b;
2691 XCharStruct *pcm;
2693 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
2694 font = face->font;
2695 font_info = FONT_INFO_FROM_ID (f, face->font_info_id);
2696 if (font
2697 && (pcm = w32_per_char_metric (hdc, font, &char2b, unicode_p)))
2699 if (pcm->rbearing > pcm->width)
2700 *right = pcm->rbearing - pcm->width;
2701 if (pcm->lbearing < 0)
2702 *left = -pcm->lbearing;
2703 xfree (pcm);
2709 static void
2710 x_get_glyph_overhangs (glyph, f, left, right)
2711 struct glyph *glyph;
2712 struct frame *f;
2713 int *left, *right;
2715 HDC hdc = get_frame_dc (f);
2716 w32_get_glyph_overhangs (hdc, glyph, f, left, right, glyph->multibyte_p);
2717 release_frame_dc (f, hdc);
2721 /* Return the index of the first glyph preceding glyph string S that
2722 is overwritten by S because of S's left overhang. Value is -1
2723 if no glyphs are overwritten. */
2725 static int
2726 x_left_overwritten (s)
2727 struct glyph_string *s;
2729 int k;
2731 if (s->left_overhang)
2733 int x = 0, i;
2734 struct glyph *glyphs = s->row->glyphs[s->area];
2735 int first = s->first_glyph - glyphs;
2737 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
2738 x -= glyphs[i].pixel_width;
2740 k = i + 1;
2742 else
2743 k = -1;
2745 return k;
2749 /* Return the index of the first glyph preceding glyph string S that
2750 is overwriting S because of its right overhang. Value is -1 if no
2751 glyph in front of S overwrites S. */
2753 static int
2754 x_left_overwriting (s)
2755 struct glyph_string *s;
2757 int i, k, x;
2758 struct glyph *glyphs = s->row->glyphs[s->area];
2759 int first = s->first_glyph - glyphs;
2761 k = -1;
2762 x = 0;
2763 for (i = first - 1; i >= 0; --i)
2765 int left, right;
2766 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left,
2767 &right, s->two_byte_p);
2768 if (x + right > 0)
2769 k = i;
2770 x -= glyphs[i].pixel_width;
2773 return k;
2777 /* Return the index of the last glyph following glyph string S that is
2778 not overwritten by S because of S's right overhang. Value is -1 if
2779 no such glyph is found. */
2781 static int
2782 x_right_overwritten (s)
2783 struct glyph_string *s;
2785 int k = -1;
2787 if (s->right_overhang)
2789 int x = 0, i;
2790 struct glyph *glyphs = s->row->glyphs[s->area];
2791 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2792 int end = s->row->used[s->area];
2794 for (i = first; i < end && s->right_overhang > x; ++i)
2795 x += glyphs[i].pixel_width;
2797 k = i;
2800 return k;
2804 /* Return the index of the last glyph following glyph string S that
2805 overwrites S because of its left overhang. Value is negative
2806 if no such glyph is found. */
2808 static int
2809 x_right_overwriting (s)
2810 struct glyph_string *s;
2812 int i, k, x;
2813 int end = s->row->used[s->area];
2814 struct glyph *glyphs = s->row->glyphs[s->area];
2815 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
2817 k = -1;
2818 x = 0;
2819 for (i = first; i < end; ++i)
2821 int left, right;
2822 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left,
2823 &right, s->two_byte_p);
2824 if (x - left < 0)
2825 k = i;
2826 x += glyphs[i].pixel_width;
2829 return k;
2833 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2835 static INLINE void
2836 x_clear_glyph_string_rect (s, x, y, w, h)
2837 struct glyph_string *s;
2838 int x, y, w, h;
2840 int real_x = x;
2841 int real_y = y;
2842 int real_w = w;
2843 int real_h = h;
2844 #if 0
2845 /* Take clipping into account. */
2846 if (s->gc->clip_mask == Rect)
2848 real_x = max (real_x, s->gc->clip_rectangle.left);
2849 real_y = max (real_y, s->gc->clip_rectangle.top);
2850 real_w = min (real_w, s->gc->clip_rectangle.right
2851 - s->gc->clip_rectangle.left);
2852 real_h = min (real_h, s->gc->clip_rectangle.bottom
2853 - s->gc->clip_rectangle.top);
2855 #endif
2856 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
2857 real_w, real_h);
2861 /* Draw the background of glyph_string S. If S->background_filled_p
2862 is non-zero don't draw it. FORCE_P non-zero means draw the
2863 background even if it wouldn't be drawn normally. This is used
2864 when a string preceding S draws into the background of S, or S
2865 contains the first component of a composition. */
2867 static void
2868 x_draw_glyph_string_background (s, force_p)
2869 struct glyph_string *s;
2870 int force_p;
2872 /* Nothing to do if background has already been drawn or if it
2873 shouldn't be drawn in the first place. */
2874 if (!s->background_filled_p)
2876 #if 0 /* NTEMACS_TODO: stipple */
2877 if (s->stippled_p)
2879 /* Fill background with a stipple pattern. */
2880 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2881 XFillRectangle (s->display, s->window, s->gc, s->x,
2882 s->y + s->face->box_line_width,
2883 s->background_width,
2884 s->height - 2 * s->face->box_line_width);
2885 XSetFillStyle (s->display, s->gc, FillSolid);
2886 s->background_filled_p = 1;
2888 else
2889 #endif
2890 if (FONT_HEIGHT (s->font) < s->height - 2 * s->face->box_line_width
2891 || s->font_not_found_p
2892 || s->extends_to_end_of_line_p
2893 || force_p)
2895 x_clear_glyph_string_rect (s, s->x, s->y + s->face->box_line_width,
2896 s->background_width,
2897 s->height - 2 * s->face->box_line_width);
2898 s->background_filled_p = 1;
2904 /* Draw the foreground of glyph string S. */
2906 static void
2907 x_draw_glyph_string_foreground (s)
2908 struct glyph_string *s;
2910 int i, x;
2912 /* If first glyph of S has a left box line, start drawing the text
2913 of S to the right of that box line. */
2914 if (s->face->box != FACE_NO_BOX
2915 && s->first_glyph->left_box_line_p)
2916 x = s->x + s->face->box_line_width;
2917 else
2918 x = s->x;
2920 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
2921 SetBkMode (s->hdc, TRANSPARENT);
2922 else
2923 SetBkMode (s->hdc, OPAQUE);
2925 SetTextColor (s->hdc, s->gc->foreground);
2926 SetBkColor (s->hdc, s->gc->background);
2927 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
2929 if (s->font && s->font->hfont)
2930 SelectObject (s->hdc, s->font->hfont);
2932 /* Draw characters of S as rectangles if S's font could not be
2933 loaded. */
2934 if (s->font_not_found_p)
2936 for (i = 0; i < s->nchars; ++i)
2938 struct glyph *g = s->first_glyph + i;
2940 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
2941 s->height - 1);
2942 x += g->pixel_width;
2945 else
2947 char *char1b = (char *) s->char2b;
2948 int boff = s->font_info->baseline_offset;
2950 if (s->font_info->vertical_centering)
2951 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2953 /* If we can use 8-bit functions, condense S->char2b. */
2954 if (!s->two_byte_p)
2955 for (i = 0; i < s->nchars; ++i)
2956 char1b[i] = BYTE2 (s->char2b[i]);
2958 /* Draw text with TextOut and friends. */
2959 W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
2963 /* Draw the foreground of composite glyph string S. */
2965 static void
2966 x_draw_composite_glyph_string_foreground (s)
2967 struct glyph_string *s;
2969 int i, x;
2971 /* If first glyph of S has a left box line, start drawing the text
2972 of S to the right of that box line. */
2973 if (s->face->box != FACE_NO_BOX
2974 && s->first_glyph->left_box_line_p)
2975 x = s->x + s->face->box_line_width;
2976 else
2977 x = s->x;
2979 /* S is a glyph string for a composition. S->gidx is the index of
2980 the first character drawn for glyphs of this composition.
2981 S->gidx == 0 means we are drawing the very first character of
2982 this composition. */
2984 SetTextColor (s->hdc, s->gc->foreground);
2985 SetBkColor (s->hdc, s->gc->background);
2986 SetBkMode (s->hdc, TRANSPARENT);
2987 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
2989 /* Draw a rectangle for the composition if the font for the very
2990 first character of the composition could not be loaded. */
2991 if (s->font_not_found_p)
2993 if (s->gidx == 0)
2994 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
2995 s->height - 1);
2997 else
2999 for (i = 0; i < s->nchars; i++, ++s->gidx)
3000 W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
3001 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3002 s->char2b + i, 1);
3006 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3007 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3008 If this produces the same color as COLOR, try a color where all RGB
3009 values have DELTA added. Return the allocated color in *COLOR.
3010 DISPLAY is the X display, CMAP is the colormap to operate on.
3011 Value is non-zero if successful. */
3013 static int
3014 w32_alloc_lighter_color (f, color, factor, delta)
3015 struct frame *f;
3016 COLORREF *color;
3017 double factor;
3018 int delta;
3020 COLORREF new;
3022 /* Change RGB values by specified FACTOR. Avoid overflow! */
3023 xassert (factor >= 0);
3024 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
3025 min (0xff, factor * GetGValue (*color)),
3026 min (0xff, factor * GetBValue (*color)));
3027 if (new == *color)
3028 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
3029 max (0, min (0xff, delta + GetGValue (*color))),
3030 max (0, min (0xff, delta + GetBValue (*color))));
3032 /* NTEMACS_TODO: Map to palette and retry with delta if same? */
3033 /* NTEMACS_TODO: Free colors (if using palette)? */
3035 if (new == *color)
3036 return 0;
3038 *color = new;
3040 return 1;
3044 /* Set up the foreground color for drawing relief lines of glyph
3045 string S. RELIEF is a pointer to a struct relief containing the GC
3046 with which lines will be drawn. Use a color that is FACTOR or
3047 DELTA lighter or darker than the relief's background which is found
3048 in S->f->output_data.x->relief_background. If such a color cannot
3049 be allocated, use DEFAULT_PIXEL, instead. */
3051 static void
3052 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
3053 struct frame *f;
3054 struct relief *relief;
3055 double factor;
3056 int delta;
3057 COLORREF default_pixel;
3059 XGCValues xgcv;
3060 struct w32_output *di = f->output_data.w32;
3061 unsigned long mask = GCForeground;
3062 COLORREF pixel;
3063 COLORREF background = di->relief_background;
3064 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3066 /* NTEMACS_TODO: Free colors (if using palette)? */
3068 /* Allocate new color. */
3069 xgcv.foreground = default_pixel;
3070 pixel = background;
3071 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
3073 relief->allocated_p = 1;
3074 xgcv.foreground = relief->pixel = pixel;
3077 if (relief->gc == 0)
3079 #if 0 /* NTEMACS_TODO: stipple */
3080 xgcv.stipple = dpyinfo->gray;
3081 mask |= GCStipple;
3082 #endif
3083 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
3085 else
3086 XChangeGC (NULL, relief->gc, mask, &xgcv);
3090 /* Set up colors for the relief lines around glyph string S. */
3092 static void
3093 x_setup_relief_colors (s)
3094 struct glyph_string *s;
3096 struct w32_output *di = s->f->output_data.w32;
3097 COLORREF color;
3099 if (s->face->use_box_color_for_shadows_p)
3100 color = s->face->box_color;
3101 else
3102 color = s->gc->background;
3104 if (di->white_relief.gc == 0
3105 || color != di->relief_background)
3107 di->relief_background = color;
3108 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3109 WHITE_PIX_DEFAULT (s->f));
3110 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3111 BLACK_PIX_DEFAULT (s->f));
3116 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3117 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3118 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3119 relief. LEFT_P non-zero means draw a relief on the left side of
3120 the rectangle. RIGHT_P non-zero means draw a relief on the right
3121 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3122 when drawing. */
3124 static void
3125 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3126 raised_p, left_p, right_p, clip_rect)
3127 struct frame *f;
3128 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3129 RECT *clip_rect;
3131 int i;
3132 XGCValues gc;
3133 HDC hdc = get_frame_dc (f);
3135 if (raised_p)
3136 gc.foreground = PALETTERGB (255, 255, 255);
3137 else
3138 gc.foreground = PALETTERGB (0, 0, 0);
3140 w32_set_clip_rectangle (hdc, clip_rect);
3142 /* Top. */
3143 for (i = 0; i < width; ++i)
3145 w32_fill_area (f, hdc, gc.foreground,
3146 left_x + i * left_p, top_y + i,
3147 (right_x + 1 - i * right_p) - (left_x + i * left_p), 1);
3150 /* Left. */
3151 if (left_p)
3152 for (i = 0; i < width; ++i)
3154 w32_fill_area (f, hdc, gc.foreground,
3155 left_x + i, top_y + i, 1,
3156 (bottom_y - i) - (top_y + i));
3159 w32_set_clip_rectangle (hdc, NULL);
3161 if (raised_p)
3162 gc.foreground = PALETTERGB (0, 0, 0);
3163 else
3164 gc.foreground = PALETTERGB (255, 255, 255);
3166 w32_set_clip_rectangle (hdc, clip_rect);
3168 /* Bottom. */
3169 for (i = 0; i < width; ++i)
3171 w32_fill_area (f, hdc, gc.foreground,
3172 left_x + i * left_p, bottom_y - i,
3173 (right_x + 1 - i * right_p) - left_x + i * left_p, 1);
3176 /* Right. */
3177 if (right_p)
3178 for (i = 0; i < width; ++i)
3180 w32_fill_area (f, hdc, gc.foreground,
3181 right_x - i, top_y + i + 1, 1,
3182 (bottom_y - i) - (top_y + i + 1));
3185 w32_set_clip_rectangle (hdc, NULL);
3187 release_frame_dc (f, hdc);
3191 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3192 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3193 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3194 left side of the rectangle. RIGHT_P non-zero means draw a line
3195 on the right side of the rectangle. CLIP_RECT is the clipping
3196 rectangle to use when drawing. */
3198 static void
3199 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3200 left_p, right_p, clip_rect)
3201 struct glyph_string *s;
3202 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3203 RECT *clip_rect;
3205 w32_set_clip_rectangle (s->hdc, clip_rect);
3207 /* Top. */
3208 w32_fill_area (s->f, s->hdc, s->face->box_color,
3209 left_x, top_y, right_x - left_x, width);
3211 /* Left. */
3212 if (left_p)
3214 w32_fill_area (s->f, s->hdc, s->face->box_color,
3215 left_x, top_y, width, bottom_y - top_y);
3218 /* Bottom. */
3219 w32_fill_area (s->f, s->hdc, s->face->box_color,
3220 left_x, bottom_y - width, right_x - left_x, width);
3222 /* Right. */
3223 if (right_p)
3225 w32_fill_area (s->f, s->hdc, s->face->box_color,
3226 right_x - width, top_y, width, bottom_y - top_y);
3229 w32_set_clip_rectangle (s->hdc, NULL);
3233 /* Draw a box around glyph string S. */
3235 static void
3236 x_draw_glyph_string_box (s)
3237 struct glyph_string *s;
3239 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3240 int left_p, right_p;
3241 struct glyph *last_glyph;
3242 RECT clip_rect;
3244 last_x = window_box_right (s->w, s->area);
3245 if (s->row->full_width_p
3246 && !s->w->pseudo_window_p)
3248 last_x += FRAME_X_RIGHT_FLAGS_AREA_WIDTH (s->f);
3249 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3250 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3253 /* The glyph that may have a right box line. */
3254 last_glyph = (s->cmp || s->img
3255 ? s->first_glyph
3256 : s->first_glyph + s->nchars - 1);
3258 width = s->face->box_line_width;
3259 raised_p = s->face->box == FACE_RAISED_BOX;
3260 left_x = s->x;
3261 right_x = ((s->row->full_width_p
3262 ? last_x - 1
3263 : min (last_x, s->x + s->background_width) - 1));
3264 top_y = s->y;
3265 bottom_y = top_y + s->height - 1;
3267 left_p = (s->first_glyph->left_box_line_p
3268 || (s->hl == DRAW_MOUSE_FACE
3269 && (s->prev == NULL
3270 || s->prev->hl != s->hl)));
3271 right_p = (last_glyph->right_box_line_p
3272 || (s->hl == DRAW_MOUSE_FACE
3273 && (s->next == NULL
3274 || s->next->hl != s->hl)));
3276 w32_get_glyph_string_clip_rect (s, &clip_rect);
3278 if (s->face->box == FACE_SIMPLE_BOX)
3279 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3280 left_p, right_p, &clip_rect);
3281 else
3283 x_setup_relief_colors (s);
3284 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3285 width, raised_p, left_p, right_p, &clip_rect);
3290 /* Draw foreground of image glyph string S. */
3292 static void
3293 x_draw_image_foreground (s)
3294 struct glyph_string *s;
3296 int x;
3297 int y = s->ybase - IMAGE_ASCENT (s->img);
3299 /* If first glyph of S has a left box line, start drawing it to the
3300 right of that line. */
3301 if (s->face->box != FACE_NO_BOX
3302 && s->first_glyph->left_box_line_p)
3303 x = s->x + s->face->box_line_width;
3304 else
3305 x = s->x;
3307 /* If there is a margin around the image, adjust x- and y-position
3308 by that margin. */
3309 if (s->img->margin)
3311 x += s->img->margin;
3312 y += s->img->margin;
3315 SaveDC (s->hdc);
3317 if (s->img->pixmap)
3319 #if 0 /* NTEMACS_TODO: image mask */
3320 if (s->img->mask)
3322 /* We can't set both a clip mask and use XSetClipRectangles
3323 because the latter also sets a clip mask. We also can't
3324 trust on the shape extension to be available
3325 (XShapeCombineRegion). So, compute the rectangle to draw
3326 manually. */
3327 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3328 | GCFunction);
3329 XGCValues xgcv;
3330 XRectangle clip_rect, image_rect, r;
3332 xgcv.clip_mask = s->img->mask;
3333 xgcv.clip_x_origin = x;
3334 xgcv.clip_y_origin = y;
3335 xgcv.function = GXcopy;
3336 XChangeGC (s->display, s->gc, mask, &xgcv);
3338 w32_get_glyph_string_clip_rect (s, &clip_rect);
3339 image_rect.x = x;
3340 image_rect.y = y;
3341 image_rect.width = s->img->width;
3342 image_rect.height = s->img->height;
3343 if (w32_intersect_rectangles (&clip_rect, &image_rect, &r))
3344 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3345 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3347 else
3348 #endif
3350 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3351 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3352 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3353 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
3355 SetTextColor (s->hdc, s->gc->foreground);
3356 SetBkColor (s->hdc, s->gc->background);
3357 #if 0 /* From w32bdf.c (which is from Meadow). */
3358 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3359 compat_hdc, 0, 0, SRCCOPY);
3360 #else
3361 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3362 compat_hdc, 0, 0, 0xB8074A);
3363 #endif
3364 SelectObject (s->hdc, orig_brush);
3365 DeleteObject (fg_brush);
3366 SelectObject (compat_hdc, orig_obj);
3367 DeleteDC (compat_hdc);
3369 /* When the image has a mask, we can expect that at
3370 least part of a mouse highlight or a block cursor will
3371 be visible. If the image doesn't have a mask, make
3372 a block cursor visible by drawing a rectangle around
3373 the image. I believe it's looking better if we do
3374 nothing here for mouse-face. */
3375 if (s->hl == DRAW_CURSOR)
3376 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
3377 s->img->height - 1);
3380 else
3381 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
3382 s->img->height - 1);
3384 RestoreDC (s->hdc ,-1);
3389 /* Draw a relief around the image glyph string S. */
3391 static void
3392 x_draw_image_relief (s)
3393 struct glyph_string *s;
3395 int x0, y0, x1, y1, thick, raised_p;
3396 RECT r;
3397 int x;
3398 int y = s->ybase - IMAGE_ASCENT (s->img);
3400 /* If first glyph of S has a left box line, start drawing it to the
3401 right of that line. */
3402 if (s->face->box != FACE_NO_BOX
3403 && s->first_glyph->left_box_line_p)
3404 x = s->x + s->face->box_line_width;
3405 else
3406 x = s->x;
3408 /* If there is a margin around the image, adjust x- and y-position
3409 by that margin. */
3410 if (s->img->margin)
3412 x += s->img->margin;
3413 y += s->img->margin;
3416 if (s->hl == DRAW_IMAGE_SUNKEN
3417 || s->hl == DRAW_IMAGE_RAISED)
3419 thick = tool_bar_button_relief > 0 ? tool_bar_button_relief : 3;
3420 raised_p = s->hl == DRAW_IMAGE_RAISED;
3422 else
3424 thick = abs (s->img->relief);
3425 raised_p = s->img->relief > 0;
3428 x0 = x - thick;
3429 y0 = y - thick;
3430 x1 = x + s->img->width + thick - 1;
3431 y1 = y + s->img->height + thick - 1;
3433 x_setup_relief_colors (s);
3434 w32_get_glyph_string_clip_rect (s, &r);
3435 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3439 /* Draw the foreground of image glyph string S to PIXMAP. */
3441 static void
3442 w32_draw_image_foreground_1 (s, pixmap)
3443 struct glyph_string *s;
3444 HBITMAP pixmap;
3446 HDC hdc = CreateCompatibleDC (s->hdc);
3447 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
3448 int x;
3449 int y = s->ybase - s->y - IMAGE_ASCENT (s->img);
3451 /* If first glyph of S has a left box line, start drawing it to the
3452 right of that line. */
3453 if (s->face->box != FACE_NO_BOX
3454 && s->first_glyph->left_box_line_p)
3455 x = s->face->box_line_width;
3456 else
3457 x = 0;
3459 /* If there is a margin around the image, adjust x- and y-position
3460 by that margin. */
3461 if (s->img->margin)
3463 x += s->img->margin;
3464 y += s->img->margin;
3467 if (s->img->pixmap)
3469 #if 0 /* NTEMACS_TODO: image mask */
3470 if (s->img->mask)
3472 /* We can't set both a clip mask and use XSetClipRectangles
3473 because the latter also sets a clip mask. We also can't
3474 trust on the shape extension to be available
3475 (XShapeCombineRegion). So, compute the rectangle to draw
3476 manually. */
3477 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3478 | GCFunction);
3479 XGCValues xgcv;
3481 xgcv.clip_mask = s->img->mask;
3482 xgcv.clip_x_origin = x;
3483 xgcv.clip_y_origin = y;
3484 xgcv.function = GXcopy;
3485 XChangeGC (s->display, s->gc, mask, &xgcv);
3487 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
3488 0, 0, s->img->width, s->img->height, x, y);
3489 XSetClipMask (s->display, s->gc, None);
3491 else
3492 #endif
3494 HDC compat_hdc = CreateCompatibleDC (hdc);
3495 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3496 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
3497 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
3499 SetTextColor (hdc, s->gc->foreground);
3500 SetBkColor (hdc, s->gc->background);
3501 #if 0 /* From w32bdf.c (which is from Meadow). */
3502 BitBlt (hdc, x, y, s->img->width, s->img->height,
3503 compat_hdc, 0, 0, SRCCOPY);
3504 #else
3505 BitBlt (hdc, x, y, s->img->width, s->img->height,
3506 compat_hdc, 0, 0, 0xB8074A);
3507 #endif
3508 SelectObject (hdc, orig_brush);
3509 DeleteObject (fg_brush);
3510 SelectObject (compat_hdc, orig_obj);
3511 DeleteDC (compat_hdc);
3513 /* When the image has a mask, we can expect that at
3514 least part of a mouse highlight or a block cursor will
3515 be visible. If the image doesn't have a mask, make
3516 a block cursor visible by drawing a rectangle around
3517 the image. I believe it's looking better if we do
3518 nothing here for mouse-face. */
3519 if (s->hl == DRAW_CURSOR)
3520 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
3521 s->img->height - 1);
3524 else
3525 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
3526 s->img->height - 1);
3528 SelectObject (hdc, orig_hdc_obj);
3529 DeleteDC (hdc);
3533 /* Draw part of the background of glyph string S. X, Y, W, and H
3534 give the rectangle to draw. */
3536 static void
3537 x_draw_glyph_string_bg_rect (s, x, y, w, h)
3538 struct glyph_string *s;
3539 int x, y, w, h;
3541 #if 0 /* NTEMACS_TODO: stipple */
3542 if (s->stippled_p)
3544 /* Fill background with a stipple pattern. */
3545 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3546 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
3547 XSetFillStyle (s->display, s->gc, FillSolid);
3549 else
3550 #endif
3551 x_clear_glyph_string_rect (s, x, y, w, h);
3555 /* Draw image glyph string S.
3557 s->y
3558 s->x +-------------------------
3559 | s->face->box
3561 | +-------------------------
3562 | | s->img->margin
3564 | | +-------------------
3565 | | | the image
3569 static void
3570 x_draw_image_glyph_string (s)
3571 struct glyph_string *s;
3573 int x, y;
3574 int box_line_width = s->face->box_line_width;
3575 int margin = s->img->margin;
3576 int height;
3577 HBITMAP pixmap = 0;
3579 height = s->height - 2 * box_line_width;
3581 /* Fill background with face under the image. Do it only if row is
3582 taller than image or if image has a clip mask to reduce
3583 flickering. */
3584 s->stippled_p = s->face->stipple != 0;
3585 if (height > s->img->height
3586 || margin
3587 #if 0 /* NTEMACS_TODO: image mask */
3588 || s->img->mask
3589 #endif
3590 || s->img->pixmap == 0
3591 || s->width != s->background_width)
3593 if (box_line_width && s->first_glyph->left_box_line_p)
3594 x = s->x + box_line_width;
3595 else
3596 x = s->x;
3598 y = s->y + box_line_width;
3599 #if 0 /* NTEMACS_TODO: image mask */
3600 if (s->img->mask)
3602 /* Create a pixmap as large as the glyph string Fill it with
3603 the background color. Copy the image to it, using its
3604 mask. Copy the temporary pixmap to the display. */
3605 Screen *screen = FRAME_X_SCREEN (s->f);
3606 int depth = DefaultDepthOfScreen (screen);
3608 /* Create a pixmap as large as the glyph string. */
3609 pixmap = XCreatePixmap (s->display, s->window,
3610 s->background_width,
3611 s->height, depth);
3613 /* Don't clip in the following because we're working on the
3614 pixmap. */
3615 XSetClipMask (s->display, s->gc, None);
3617 /* Fill the pixmap with the background color/stipple. */
3618 if (s->stippled_p)
3620 /* Fill background with a stipple pattern. */
3621 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3622 XFillRectangle (s->display, pixmap, s->gc,
3623 0, 0, s->background_width, s->height);
3624 XSetFillStyle (s->display, s->gc, FillSolid);
3626 else
3628 XGCValues xgcv;
3629 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
3630 &xgcv);
3631 XSetForeground (s->display, s->gc, xgcv.background);
3632 XFillRectangle (s->display, pixmap, s->gc,
3633 0, 0, s->background_width, s->height);
3634 XSetForeground (s->display, s->gc, xgcv.foreground);
3637 else
3638 #endif
3639 /* Implementation idea: Is it possible to construct a mask?
3640 We could look at the color at the margins of the image, and
3641 say that this color is probably the background color of the
3642 image. */
3643 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
3645 s->background_filled_p = 1;
3648 /* Draw the foreground. */
3649 if (pixmap != 0)
3651 w32_draw_image_foreground_1 (s, pixmap);
3652 x_set_glyph_string_clipping (s);
3654 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3655 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3656 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3657 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
3659 SetTextColor (s->hdc, s->gc->foreground);
3660 SetBkColor (s->hdc, s->gc->background);
3661 #if 0 /* From w32bdf.c (which is from Meadow). */
3662 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
3663 compat_hdc, 0, 0, SRCCOPY);
3664 #else
3665 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
3666 compat_hdc, 0, 0, 0xB8074A);
3667 #endif
3668 SelectObject (s->hdc, orig_brush);
3669 DeleteObject (fg_brush);
3670 SelectObject (compat_hdc, orig_obj);
3671 DeleteDC (compat_hdc);
3673 DeleteObject (pixmap);
3674 pixmap = 0;
3676 else
3677 x_draw_image_foreground (s);
3679 /* If we must draw a relief around the image, do it. */
3680 if (s->img->relief
3681 || s->hl == DRAW_IMAGE_RAISED
3682 || s->hl == DRAW_IMAGE_SUNKEN)
3683 x_draw_image_relief (s);
3687 /* Draw stretch glyph string S. */
3689 static void
3690 x_draw_stretch_glyph_string (s)
3691 struct glyph_string *s;
3693 xassert (s->first_glyph->type == STRETCH_GLYPH);
3694 s->stippled_p = s->face->stipple != 0;
3696 if (s->hl == DRAW_CURSOR
3697 && !x_stretch_cursor_p)
3699 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3700 as wide as the stretch glyph. */
3701 int width = min (CANON_X_UNIT (s->f), s->background_width);
3703 /* Draw cursor. */
3704 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3706 /* Clear rest using the GC of the original non-cursor face. */
3707 if (width < s->background_width)
3709 XGCValues *gc = s->face->gc;
3710 int x = s->x + width, y = s->y;
3711 int w = s->background_width - width, h = s->height;
3712 RECT r;
3713 HDC hdc = s->hdc;
3714 w32_get_glyph_string_clip_rect (s, &r);
3715 w32_set_clip_rectangle (hdc, &r);
3717 #if 0 /* NTEMACS_TODO: stipple */
3718 if (s->face->stipple)
3720 /* Fill background with a stipple pattern. */
3721 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3722 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3723 XSetFillStyle (s->display, gc, FillSolid);
3725 else
3726 #endif
3728 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
3732 else
3733 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3734 s->height);
3736 s->background_filled_p = 1;
3740 /* Draw glyph string S. */
3742 static void
3743 x_draw_glyph_string (s)
3744 struct glyph_string *s;
3746 /* If S draws into the background of its successor, draw the
3747 background of the successor first so that S can draw into it.
3748 This makes S->next use XDrawString instead of XDrawImageString. */
3749 if (s->next && s->right_overhang && !s->for_overlaps_p)
3751 xassert (s->next->img == NULL);
3752 x_set_glyph_string_gc (s->next);
3753 x_set_glyph_string_clipping (s->next);
3754 x_draw_glyph_string_background (s->next, 1);
3757 /* Set up S->gc, set clipping and draw S. */
3758 x_set_glyph_string_gc (s);
3759 x_set_glyph_string_clipping (s);
3761 switch (s->first_glyph->type)
3763 case IMAGE_GLYPH:
3764 x_draw_image_glyph_string (s);
3765 break;
3767 case STRETCH_GLYPH:
3768 x_draw_stretch_glyph_string (s);
3769 break;
3771 case CHAR_GLYPH:
3772 if (s->for_overlaps_p)
3773 s->background_filled_p = 1;
3774 else
3775 x_draw_glyph_string_background (s, 0);
3776 x_draw_glyph_string_foreground (s);
3777 break;
3779 case COMPOSITE_GLYPH:
3780 if (s->for_overlaps_p || s->gidx > 0)
3781 s->background_filled_p = 1;
3782 else
3783 x_draw_glyph_string_background (s, 1);
3784 x_draw_composite_glyph_string_foreground (s);
3785 break;
3787 default:
3788 abort ();
3791 if (!s->for_overlaps_p)
3793 /* Draw underline. */
3794 if (s->face->underline_p && (!s->font->bdf && !s->font->tm.tmUnderlined))
3796 unsigned long h = 1;
3797 unsigned long dy = s->height - h;
3799 if (s->face->underline_defaulted_p)
3801 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
3802 s->y + dy, s->width, 1);
3804 else
3806 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3807 s->y + dy, s->width, 1);
3811 /* Draw overline. */
3812 if (s->face->overline_p)
3814 unsigned long dy = 0, h = 1;
3816 if (s->face->overline_color_defaulted_p)
3818 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
3819 s->y + dy, s->width, h);
3821 else
3823 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3824 s->y + dy, s->width, h);
3828 /* Draw strike-through. */
3829 if (s->face->strike_through_p && (!s->font->bdf &&!s->font->tm.tmStruckOut))
3831 unsigned long h = 1;
3832 unsigned long dy = (s->height - h) / 2;
3834 if (s->face->strike_through_color_defaulted_p)
3836 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
3837 s->width, h);
3839 else
3841 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
3842 s->y + dy, s->width, h);
3846 /* Draw relief. */
3847 if (s->face->box != FACE_NO_BOX)
3848 x_draw_glyph_string_box (s);
3851 /* Reset clipping. */
3852 w32_set_clip_rectangle (s->hdc, NULL);
3856 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
3857 struct face **, int));
3860 /* Load glyph string S with a composition components specified by S->cmp.
3861 FACES is an array of faces for all components of this composition.
3862 S->gidx is the index of the first component for S.
3863 OVERLAPS_P non-zero means S should draw the foreground only, and
3864 use its lines physical height for clipping.
3866 Value is the index of a component not in S. */
3868 static int
3869 x_fill_composite_glyph_string (s, faces, overlaps_p)
3870 struct glyph_string *s;
3871 struct face **faces;
3872 int overlaps_p;
3874 int i;
3876 xassert (s);
3878 s->for_overlaps_p = overlaps_p;
3880 s->face = faces[s->gidx];
3881 s->font = s->face->font;
3882 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3884 /* For all glyphs of this composition, starting at the offset
3885 S->gidx, until we reach the end of the definition or encounter a
3886 glyph that requires the different face, add it to S. */
3887 ++s->nchars;
3888 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
3889 ++s->nchars;
3891 /* All glyph strings for the same composition has the same width,
3892 i.e. the width set for the first component of the composition. */
3894 s->width = s->first_glyph->pixel_width;
3896 /* If the specified font could not be loaded, use the frame's
3897 default font, but record the fact that we couldn't load it in
3898 the glyph string so that we can draw rectangles for the
3899 characters of the glyph string. */
3900 if (s->font == NULL)
3902 s->font_not_found_p = 1;
3903 s->font = FRAME_FONT (s->f);
3906 /* Adjust base line for subscript/superscript text. */
3907 s->ybase += s->first_glyph->voffset;
3909 xassert (s->face && s->face->gc);
3911 /* This glyph string must always be drawn with 16-bit functions. */
3912 s->two_byte_p = 1;
3914 return s->gidx + s->nchars;
3918 /* Load glyph string S with a sequence of characters.
3919 FACE_ID is the face id of the string. START is the index of the
3920 first glyph to consider, END is the index of the last + 1.
3921 OVERLAPS_P non-zero means S should draw the foreground only, and
3922 use its lines physical height for clipping.
3924 Value is the index of the first glyph not in S. */
3926 static int
3927 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
3928 struct glyph_string *s;
3929 int face_id;
3930 int start, end, overlaps_p;
3932 struct glyph *glyph, *last;
3933 int voffset;
3934 int glyph_not_available_p;
3936 xassert (s->f == XFRAME (s->w->frame));
3937 xassert (s->nchars == 0);
3938 xassert (start >= 0 && end > start);
3940 s->for_overlaps_p = overlaps_p;
3942 glyph = s->row->glyphs[s->area] + start;
3943 last = s->row->glyphs[s->area] + end;
3944 voffset = glyph->voffset;
3946 glyph_not_available_p = glyph->glyph_not_available_p;
3948 while (glyph < last
3949 && glyph->type == CHAR_GLYPH
3950 && glyph->voffset == voffset
3951 /* Same face id implies same font, nowadays. */
3952 && glyph->face_id == face_id
3953 && glyph->glyph_not_available_p == glyph_not_available_p)
3955 int two_byte_p;
3957 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
3958 s->char2b + s->nchars,
3959 &two_byte_p);
3960 s->two_byte_p = two_byte_p;
3961 ++s->nchars;
3962 xassert (s->nchars <= end - start);
3963 s->width += glyph->pixel_width;
3964 ++glyph;
3967 s->font = s->face->font;
3968 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
3970 /* If the specified font could not be loaded, use the frame's font,
3971 but record the fact that we couldn't load it in
3972 S->font_not_found_p so that we can draw rectangles for the
3973 characters of the glyph string. */
3974 if (s->font == NULL || glyph_not_available_p)
3976 s->font_not_found_p = 1;
3977 s->font = FRAME_FONT (s->f);
3980 /* Adjust base line for subscript/superscript text. */
3981 s->ybase += voffset;
3983 xassert (s->face && s->face->gc);
3984 return glyph - s->row->glyphs[s->area];
3988 /* Fill glyph string S from image glyph S->first_glyph. */
3990 static void
3991 x_fill_image_glyph_string (s)
3992 struct glyph_string *s;
3994 xassert (s->first_glyph->type == IMAGE_GLYPH);
3995 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
3996 xassert (s->img);
3997 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
3998 s->font = s->face->font;
3999 s->width = s->first_glyph->pixel_width;
4001 /* Adjust base line for subscript/superscript text. */
4002 s->ybase += s->first_glyph->voffset;
4006 /* Fill glyph string S from stretch glyph S->first_glyph. */
4008 static void
4009 x_fill_stretch_glyph_string (s)
4010 struct glyph_string *s;
4012 xassert (s->first_glyph->type == STRETCH_GLYPH);
4013 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4014 s->font = s->face->font;
4015 s->width = s->first_glyph->pixel_width;
4017 /* Adjust base line for subscript/superscript text. */
4018 s->ybase += s->first_glyph->voffset;
4022 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4023 of XChar2b structures for S; it can't be allocated in
4024 x_init_glyph_string because it must be allocated via `alloca'. W
4025 is the window on which S is drawn. ROW and AREA are the glyph row
4026 and area within the row from which S is constructed. START is the
4027 index of the first glyph structure covered by S. HL is a
4028 face-override for drawing S. */
4030 static void
4031 w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
4032 struct glyph_string *s;
4033 HDC hdc;
4034 wchar_t *char2b;
4035 struct window *w;
4036 struct glyph_row *row;
4037 enum glyph_row_area area;
4038 int start;
4039 enum draw_glyphs_face hl;
4041 bzero (s, sizeof *s);
4042 s->w = w;
4043 s->f = XFRAME (w->frame);
4044 s->hdc = hdc;
4045 s->window = FRAME_W32_WINDOW (s->f);
4046 s->char2b = char2b;
4047 s->hl = hl;
4048 s->row = row;
4049 s->area = area;
4050 s->first_glyph = row->glyphs[area] + start;
4051 s->height = row->height;
4052 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4054 /* Display the internal border below the tool-bar window. */
4055 if (s->w == XWINDOW (s->f->tool_bar_window))
4056 s->y -= s->f->output_data.w32->internal_border_width;
4058 s->ybase = s->y + row->ascent;
4062 /* Set background width of glyph string S. START is the index of the
4063 first glyph following S. LAST_X is the right-most x-position + 1
4064 in the drawing area. */
4066 static INLINE void
4067 x_set_glyph_string_background_width (s, start, last_x)
4068 struct glyph_string *s;
4069 int start;
4070 int last_x;
4072 /* If the face of this glyph string has to be drawn to the end of
4073 the drawing area, set S->extends_to_end_of_line_p. */
4074 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4076 if (start == s->row->used[s->area]
4077 && s->hl == DRAW_NORMAL_TEXT
4078 && ((s->area == TEXT_AREA && s->row->fill_line_p)
4079 || s->face->background != default_face->background
4080 || s->face->stipple != default_face->stipple))
4081 s->extends_to_end_of_line_p = 1;
4083 /* If S extends its face to the end of the line, set its
4084 background_width to the distance to the right edge of the drawing
4085 area. */
4086 if (s->extends_to_end_of_line_p)
4087 s->background_width = last_x - s->x + 1;
4088 else
4089 s->background_width = s->width;
4093 /* Add a glyph string for a stretch glyph to the list of strings
4094 between HEAD and TAIL. START is the index of the stretch glyph in
4095 row area AREA of glyph row ROW. END is the index of the last glyph
4096 in that glyph row area. X is the current output position assigned
4097 to the new glyph string constructed. HL overrides that face of the
4098 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4099 is the right-most x-position of the drawing area. */
4101 #define BUILD_STRETCH_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4102 do \
4104 s = (struct glyph_string *) alloca (sizeof *s); \
4105 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4106 x_fill_stretch_glyph_string (s); \
4107 x_append_glyph_string (&HEAD, &TAIL, s); \
4108 ++START; \
4109 s->x = (X); \
4111 while (0)
4114 /* Add a glyph string for an image glyph to the list of strings
4115 between HEAD and TAIL. START is the index of the image glyph in
4116 row area AREA of glyph row ROW. END is the index of the last glyph
4117 in that glyph row area. X is the current output position assigned
4118 to the new glyph string constructed. HL overrides that face of the
4119 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4120 is the right-most x-position of the drawing area. */
4122 #define BUILD_IMAGE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4123 do \
4125 s = (struct glyph_string *) alloca (sizeof *s); \
4126 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4127 x_fill_image_glyph_string (s); \
4128 x_append_glyph_string (&HEAD, &TAIL, s); \
4129 ++START; \
4130 s->x = (X); \
4132 while (0)
4135 /* Add a glyph string for a sequence of character glyphs to the list
4136 of strings between HEAD and TAIL. START is the index of the first
4137 glyph in row area AREA of glyph row ROW that is part of the new
4138 glyph string. END is the index of the last glyph in that glyph row
4139 area. X is the current output position assigned to the new glyph
4140 string constructed. HL overrides that face of the glyph; e.g. it
4141 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4142 right-most x-position of the drawing area. */
4144 #define BUILD_CHAR_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4145 do \
4147 int c, charset, face_id; \
4148 wchar_t *char2b; \
4150 c = (ROW)->glyphs[AREA][START].u.ch; \
4151 face_id = (ROW)->glyphs[AREA][START].face_id; \
4152 s = (struct glyph_string *) alloca (sizeof *s); \
4153 char2b = (wchar_t *) alloca ((END - START) * sizeof *char2b); \
4154 w32_init_glyph_string (s, hdc, char2b, W, ROW, AREA, START, HL); \
4155 x_append_glyph_string (&HEAD, &TAIL, s); \
4156 s->x = (X); \
4157 START = x_fill_glyph_string (s, face_id, START, END, \
4158 OVERLAPS_P); \
4160 while (0)
4163 /* Add a glyph string for a composite sequence to the list of strings
4164 between HEAD and TAIL. START is the index of the first glyph in
4165 row area AREA of glyph row ROW that is part of the new glyph
4166 string. END is the index of the last glyph in that glyph row area.
4167 X is the current output position assigned to the new glyph string
4168 constructed. HL overrides that face of the glyph; e.g. it is
4169 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4170 x-position of the drawing area. */
4172 #define BUILD_COMPOSITE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4173 do { \
4174 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4175 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4176 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4177 struct composition *cmp = composition_table[cmp_id]; \
4178 int glyph_len = cmp->glyph_len; \
4179 wchar_t *char2b; \
4180 struct face **faces; \
4181 struct glyph_string *first_s = NULL; \
4182 int n; \
4184 base_face = base_face->ascii_face; \
4185 char2b = (wchar_t *) alloca ((sizeof *char2b) * glyph_len); \
4186 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4187 /* At first, fill in `char2b' and `faces'. */ \
4188 for (n = 0; n < glyph_len; n++) \
4190 int c = COMPOSITION_GLYPH (cmp, n); \
4191 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4192 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4193 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4194 this_face_id, char2b + n, 1); \
4197 /* Make glyph_strings for each glyph sequence that is drawable by \
4198 the same face, and append them to HEAD/TAIL. */ \
4199 for (n = 0; n < cmp->glyph_len;) \
4201 s = (struct glyph_string *) alloca (sizeof *s); \
4202 w32_init_glyph_string (s, hdc, char2b + n, W, ROW, AREA, START, HL); \
4203 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4204 s->cmp = cmp; \
4205 s->gidx = n; \
4206 s->x = (X); \
4208 if (n == 0) \
4209 first_s = s; \
4211 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4214 ++START; \
4215 s = first_s; \
4216 } while (0)
4218 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4219 of AREA of glyph row ROW on window W between indices START and END.
4220 HL overrides the face for drawing glyph strings, e.g. it is
4221 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4222 x-positions of the drawing area.
4224 This is an ugly monster macro construct because we must use alloca
4225 to allocate glyph strings (because x_draw_glyphs can be called
4226 asynchronously). */
4228 #define BUILD_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4229 do \
4231 HEAD = TAIL = NULL; \
4232 while (START < END) \
4234 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4235 switch (first_glyph->type) \
4237 case CHAR_GLYPH: \
4238 BUILD_CHAR_GLYPH_STRINGS (hdc, W, ROW, AREA, START, END, \
4239 HEAD, TAIL, HL, X, LAST_X, \
4240 OVERLAPS_P); \
4241 break; \
4243 case COMPOSITE_GLYPH: \
4244 BUILD_COMPOSITE_GLYPH_STRING (hdc, W, ROW, AREA, START, \
4245 END, HEAD, TAIL, HL, X, \
4246 LAST_X, OVERLAPS_P); \
4247 break; \
4249 case STRETCH_GLYPH: \
4250 BUILD_STRETCH_GLYPH_STRING (hdc, W, ROW, AREA, START, END,\
4251 HEAD, TAIL, HL, X, LAST_X); \
4252 break; \
4254 case IMAGE_GLYPH: \
4255 BUILD_IMAGE_GLYPH_STRING (hdc, W, ROW, AREA, START, END, \
4256 HEAD, TAIL, HL, X, LAST_X); \
4257 break; \
4259 default: \
4260 abort (); \
4263 x_set_glyph_string_background_width (s, START, LAST_X); \
4264 (X) += s->width; \
4267 while (0)
4270 /* Draw glyphs between START and END in AREA of ROW on window W,
4271 starting at x-position X. X is relative to AREA in W. HL is a
4272 face-override with the following meaning:
4274 DRAW_NORMAL_TEXT draw normally
4275 DRAW_CURSOR draw in cursor face
4276 DRAW_MOUSE_FACE draw in mouse face.
4277 DRAW_INVERSE_VIDEO draw in mode line face
4278 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4279 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4281 If REAL_START is non-null, return in *REAL_START the real starting
4282 position for display. This can be different from START in case
4283 overlapping glyphs must be displayed. If REAL_END is non-null,
4284 return in *REAL_END the real end position for display. This can be
4285 different from END in case overlapping glyphs must be displayed.
4287 If OVERLAPS_P is non-zero, draw only the foreground of characters
4288 and clip to the physical height of ROW.
4290 Value is the x-position reached, relative to AREA of W. */
4292 static int
4293 x_draw_glyphs (w, x, row, area, start, end, hl, real_start, real_end,
4294 overlaps_p)
4295 struct window *w;
4296 int x;
4297 struct glyph_row *row;
4298 enum glyph_row_area area;
4299 int start, end;
4300 enum draw_glyphs_face hl;
4301 int *real_start, *real_end;
4302 int overlaps_p;
4304 struct glyph_string *head, *tail;
4305 struct glyph_string *s;
4306 int last_x, area_width;
4307 int x_reached;
4308 int i, j;
4309 HDC hdc = get_frame_dc (XFRAME (WINDOW_FRAME (w)));
4311 /* Let's rather be paranoid than getting a SEGV. */
4312 start = max (0, start);
4313 end = min (end, row->used[area]);
4314 if (real_start)
4315 *real_start = start;
4316 if (real_end)
4317 *real_end = end;
4319 /* Translate X to frame coordinates. Set last_x to the right
4320 end of the drawing area. */
4321 if (row->full_width_p)
4323 struct frame *f = XFRAME (WINDOW_FRAME (w));
4325 /* X is relative to the left edge of W, without scroll bars
4326 or flag areas. */
4327 /* int width = FRAME_FLAGS_AREA_WIDTH (f); */
4328 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4330 x += window_left_x;
4331 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4332 last_x = window_left_x + area_width;
4334 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4336 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4337 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4338 last_x += width;
4339 else
4340 x -= width;
4343 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4344 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4346 else
4348 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4349 area_width = window_box_width (w, area);
4350 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4353 /* Build a doubly-linked list of glyph_string structures between
4354 head and tail from what we have to draw. Note that the macro
4355 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4356 the reason we use a separate variable `i'. */
4357 i = start;
4358 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, end, head, tail, hl, x, last_x,
4359 overlaps_p);
4361 if (tail)
4362 x_reached = tail->x + tail->background_width;
4363 else
4364 x_reached = x;
4366 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4367 the row, redraw some glyphs in front or following the glyph
4368 strings built above. */
4369 if (!overlaps_p && row->contains_overlapping_glyphs_p)
4371 int dummy_x = 0;
4372 struct glyph_string *h, *t;
4374 /* Compute overhangs for all glyph strings. */
4375 for (s = head; s; s = s->next)
4376 x_compute_glyph_string_overhangs (s);
4378 /* Prepend glyph strings for glyphs in front of the first glyph
4379 string that are overwritten because of the first glyph
4380 string's left overhang. The background of all strings
4381 prepended must be drawn because the first glyph string
4382 draws over it. */
4383 i = x_left_overwritten (head);
4384 if (i >= 0)
4386 j = i;
4387 BUILD_GLYPH_STRINGS (hdc, w, row, area, j, start, h, t,
4388 DRAW_NORMAL_TEXT, dummy_x, last_x,
4389 overlaps_p);
4390 start = i;
4391 if (real_start)
4392 *real_start = start;
4393 x_compute_overhangs_and_x (t, head->x, 1);
4394 x_prepend_glyph_string_lists (&head, &tail, h, t);
4397 /* Prepend glyph strings for glyphs in front of the first glyph
4398 string that overwrite that glyph string because of their
4399 right overhang. For these strings, only the foreground must
4400 be drawn, because it draws over the glyph string at `head'.
4401 The background must not be drawn because this would overwrite
4402 right overhangs of preceding glyphs for which no glyph
4403 strings exist. */
4404 i = x_left_overwriting (head);
4405 if (i >= 0)
4407 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, start, h, t,
4408 DRAW_NORMAL_TEXT, dummy_x, last_x,
4409 overlaps_p);
4411 for (s = h; s; s = s->next)
4412 s->background_filled_p = 1;
4413 if (real_start)
4414 *real_start = i;
4415 x_compute_overhangs_and_x (t, head->x, 1);
4416 x_prepend_glyph_string_lists (&head, &tail, h, t);
4419 /* Append glyphs strings for glyphs following the last glyph
4420 string tail that are overwritten by tail. The background of
4421 these strings has to be drawn because tail's foreground draws
4422 over it. */
4423 i = x_right_overwritten (tail);
4424 if (i >= 0)
4426 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
4427 DRAW_NORMAL_TEXT, x, last_x,
4428 overlaps_p);
4430 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4431 x_append_glyph_string_lists (&head, &tail, h, t);
4432 if (real_end)
4433 *real_end = i;
4436 /* Append glyph strings for glyphs following the last glyph
4437 string tail that overwrite tail. The foreground of such
4438 glyphs has to be drawn because it writes into the background
4439 of tail. The background must not be drawn because it could
4440 paint over the foreground of following glyphs. */
4441 i = x_right_overwriting (tail);
4442 if (i >= 0)
4444 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
4445 DRAW_NORMAL_TEXT, x, last_x,
4446 overlaps_p);
4448 for (s = h; s; s = s->next)
4449 s->background_filled_p = 1;
4450 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
4451 x_append_glyph_string_lists (&head, &tail, h, t);
4452 if (real_end)
4453 *real_end = i;
4457 /* Draw all strings. */
4458 for (s = head; s; s = s->next)
4459 x_draw_glyph_string (s);
4461 /* Value is the x-position up to which drawn, relative to AREA of W.
4462 This doesn't include parts drawn because of overhangs. */
4463 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
4464 if (!row->full_width_p)
4466 if (area > LEFT_MARGIN_AREA)
4467 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
4468 if (area > TEXT_AREA)
4469 x_reached -= window_box_width (w, TEXT_AREA);
4472 release_frame_dc (XFRAME (WINDOW_FRAME (w)), hdc);
4474 return x_reached;
4478 /* Fix the display of area AREA of overlapping row ROW in window W. */
4480 static void
4481 x_fix_overlapping_area (w, row, area)
4482 struct window *w;
4483 struct glyph_row *row;
4484 enum glyph_row_area area;
4486 int i, x;
4488 BLOCK_INPUT;
4490 if (area == LEFT_MARGIN_AREA)
4491 x = 0;
4492 else if (area == TEXT_AREA)
4493 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4494 else
4495 x = (window_box_width (w, LEFT_MARGIN_AREA)
4496 + window_box_width (w, TEXT_AREA));
4498 for (i = 0; i < row->used[area];)
4500 if (row->glyphs[area][i].overlaps_vertically_p)
4502 int start = i, start_x = x;
4506 x += row->glyphs[area][i].pixel_width;
4507 ++i;
4509 while (i < row->used[area]
4510 && row->glyphs[area][i].overlaps_vertically_p);
4512 x_draw_glyphs (w, start_x, row, area, start, i,
4513 (row->inverse_p
4514 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4515 NULL, NULL, 1);
4517 else
4519 x += row->glyphs[area][i].pixel_width;
4520 ++i;
4524 UNBLOCK_INPUT;
4528 /* Output LEN glyphs starting at START at the nominal cursor position.
4529 Advance the nominal cursor over the text. The global variable
4530 updated_window contains the window being updated, updated_row is
4531 the glyph row being updated, and updated_area is the area of that
4532 row being updated. */
4534 static void
4535 x_write_glyphs (start, len)
4536 struct glyph *start;
4537 int len;
4539 int x, hpos, real_start, real_end;
4541 xassert (updated_window && updated_row);
4542 BLOCK_INPUT;
4544 /* Write glyphs. */
4546 hpos = start - updated_row->glyphs[updated_area];
4547 x = x_draw_glyphs (updated_window, output_cursor.x,
4548 updated_row, updated_area,
4549 hpos, hpos + len,
4550 (updated_row->inverse_p
4551 ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT),
4552 &real_start, &real_end, 0);
4554 /* If we drew over the cursor, note that it is not visible any more. */
4555 note_overwritten_text_cursor (updated_window, real_start,
4556 real_end - real_start);
4558 UNBLOCK_INPUT;
4560 /* Advance the output cursor. */
4561 output_cursor.hpos += len;
4562 output_cursor.x = x;
4566 /* Insert LEN glyphs from START at the nominal cursor position. */
4568 static void
4569 x_insert_glyphs (start, len)
4570 struct glyph *start;
4571 register int len;
4573 struct frame *f;
4574 struct window *w;
4575 int line_height, shift_by_width, shifted_region_width;
4576 struct glyph_row *row;
4577 struct glyph *glyph;
4578 int frame_x, frame_y, hpos, real_start, real_end;
4579 HDC hdc;
4581 xassert (updated_window && updated_row);
4582 BLOCK_INPUT;
4583 w = updated_window;
4584 f = XFRAME (WINDOW_FRAME (w));
4585 hdc = get_frame_dc (f);
4587 /* Get the height of the line we are in. */
4588 row = updated_row;
4589 line_height = row->height;
4591 /* Get the width of the glyphs to insert. */
4592 shift_by_width = 0;
4593 for (glyph = start; glyph < start + len; ++glyph)
4594 shift_by_width += glyph->pixel_width;
4596 /* Get the width of the region to shift right. */
4597 shifted_region_width = (window_box_width (w, updated_area)
4598 - output_cursor.x
4599 - shift_by_width);
4601 /* Shift right. */
4602 frame_x = WINDOW_TO_FRAME_PIXEL_X (w, output_cursor.x);
4603 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
4604 BitBlt (hdc, frame_x + shift_by_width, frame_y,
4605 shifted_region_width, line_height,
4606 hdc, frame_x, frame_y, SRCCOPY);
4608 /* Write the glyphs. */
4609 hpos = start - row->glyphs[updated_area];
4610 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
4611 DRAW_NORMAL_TEXT, &real_start, &real_end, 0);
4612 note_overwritten_text_cursor (w, real_start, real_end - real_start);
4614 /* Advance the output cursor. */
4615 output_cursor.hpos += len;
4616 output_cursor.x += shift_by_width;
4617 release_frame_dc (f, hdc);
4619 UNBLOCK_INPUT;
4623 /* Delete N glyphs at the nominal cursor position. Not implemented
4624 for X frames. */
4626 static void
4627 x_delete_glyphs (n)
4628 register int n;
4630 abort ();
4634 /* Erase the current text line from the nominal cursor position
4635 (inclusive) to pixel column TO_X (exclusive). The idea is that
4636 everything from TO_X onward is already erased.
4638 TO_X is a pixel position relative to updated_area of
4639 updated_window. TO_X == -1 means clear to the end of this area. */
4641 static void
4642 x_clear_end_of_line (to_x)
4643 int to_x;
4645 struct frame *f;
4646 struct window *w = updated_window;
4647 int max_x, min_y, max_y;
4648 int from_x, from_y, to_y;
4650 xassert (updated_window && updated_row);
4651 f = XFRAME (w->frame);
4653 if (updated_row->full_width_p)
4655 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
4656 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
4657 && !w->pseudo_window_p)
4658 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4660 else
4661 max_x = window_box_width (w, updated_area);
4662 max_y = window_text_bottom_y (w);
4664 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
4665 of window. For TO_X > 0, truncate to end of drawing area. */
4666 if (to_x == 0)
4667 return;
4668 else if (to_x < 0)
4669 to_x = max_x;
4670 else
4671 to_x = min (to_x, max_x);
4673 to_y = min (max_y, output_cursor.y + updated_row->height);
4675 /* Notice if the cursor will be cleared by this operation. */
4676 if (!updated_row->full_width_p)
4677 note_overwritten_text_cursor (w, output_cursor.hpos, -1);
4679 from_x = output_cursor.x;
4681 /* Translate to frame coordinates. */
4682 if (updated_row->full_width_p)
4684 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
4685 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
4687 else
4689 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
4690 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
4693 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
4694 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
4695 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
4697 /* Prevent inadvertently clearing to end of the X window. */
4698 if (to_x > from_x && to_y > from_y)
4700 HDC hdc;
4701 BLOCK_INPUT;
4702 hdc = get_frame_dc (f);
4704 w32_clear_area (f, hdc, from_x, from_y, to_x - from_x, to_y - from_y);
4705 release_frame_dc (f, hdc);
4706 UNBLOCK_INPUT;
4711 /* Clear entire frame. If updating_frame is non-null, clear that
4712 frame. Otherwise clear the selected frame. */
4714 static void
4715 x_clear_frame ()
4717 struct frame *f;
4719 if (updating_frame)
4720 f = updating_frame;
4721 else
4722 f = SELECTED_FRAME ();
4724 /* Clearing the frame will erase any cursor, so mark them all as no
4725 longer visible. */
4726 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
4727 output_cursor.hpos = output_cursor.vpos = 0;
4728 output_cursor.x = -1;
4730 /* We don't set the output cursor here because there will always
4731 follow an explicit cursor_to. */
4732 BLOCK_INPUT;
4734 w32_clear_window (f);
4736 /* We have to clear the scroll bars, too. If we have changed
4737 colors or something like that, then they should be notified. */
4738 x_scroll_bar_clear (f);
4740 UNBLOCK_INPUT;
4744 /* Make audible bell. */
4746 static void
4747 w32_ring_bell (void)
4749 BLOCK_INPUT;
4751 if (visible_bell)
4753 int i;
4754 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
4756 for (i = 0; i < 5; i++)
4758 FlashWindow (hwnd, TRUE);
4759 Sleep (10);
4761 FlashWindow (hwnd, FALSE);
4763 else
4764 w32_sys_ring_bell ();
4766 UNBLOCK_INPUT;
4770 /* Specify how many text lines, from the top of the window,
4771 should be affected by insert-lines and delete-lines operations.
4772 This, and those operations, are used only within an update
4773 that is bounded by calls to x_update_begin and x_update_end. */
4775 static void
4776 w32_set_terminal_window (n)
4777 register int n;
4779 /* This function intentionally left blank. */
4784 /***********************************************************************
4785 Line Dance
4786 ***********************************************************************/
4788 /* Perform an insert-lines or delete-lines operation, inserting N
4789 lines or deleting -N lines at vertical position VPOS. */
4791 static void
4792 x_ins_del_lines (vpos, n)
4793 int vpos, n;
4795 abort ();
4799 /* Scroll part of the display as described by RUN. */
4801 static void
4802 x_scroll_run (w, run)
4803 struct window *w;
4804 struct run *run;
4806 struct frame *f = XFRAME (w->frame);
4807 int x, y, width, height, from_y, to_y, bottom_y;
4808 HDC hdc = get_frame_dc (f);
4810 /* Get frame-relative bounding box of the text display area of W,
4811 without mode lines. Include in this box the flags areas to the
4812 left and right of W. */
4813 window_box (w, -1, &x, &y, &width, &height);
4814 width += FRAME_X_FLAGS_AREA_WIDTH (f);
4815 x -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
4817 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
4818 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
4819 bottom_y = y + height;
4821 if (to_y < from_y)
4823 /* Scrolling up. Make sure we don't copy part of the mode
4824 line at the bottom. */
4825 if (from_y + run->height > bottom_y)
4826 height = bottom_y - from_y;
4827 else
4828 height = run->height;
4830 else
4832 /* Scolling down. Make sure we don't copy over the mode line.
4833 at the bottom. */
4834 if (to_y + run->height > bottom_y)
4835 height = bottom_y - to_y;
4836 else
4837 height = run->height;
4840 BLOCK_INPUT;
4842 /* Cursor off. Will be switched on again in x_update_window_end. */
4843 updated_window = w;
4844 x_clear_cursor (w);
4846 BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY);
4848 UNBLOCK_INPUT;
4849 release_frame_dc (f, hdc);
4853 /***********************************************************************
4854 Exposure Events
4855 ***********************************************************************/
4857 /* Redisplay an exposed area of frame F. X and Y are the upper-left
4858 corner of the exposed rectangle. W and H are width and height of
4859 the exposed area. All are pixel values. W or H zero means redraw
4860 the entire frame. */
4862 static void
4863 expose_frame (f, x, y, w, h)
4864 struct frame *f;
4865 int x, y, w, h;
4867 RECT r;
4869 TRACE ((stderr, "expose_frame "));
4871 /* No need to redraw if frame will be redrawn soon. */
4872 if (FRAME_GARBAGED_P (f))
4874 TRACE ((stderr, " garbaged\n"));
4875 return;
4878 /* If basic faces haven't been realized yet, there is no point in
4879 trying to redraw anything. This can happen when we get an expose
4880 event while Emacs is starting, e.g. by moving another window. */
4881 if (FRAME_FACE_CACHE (f) == NULL
4882 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
4884 TRACE ((stderr, " no faces\n"));
4885 return;
4888 if (w == 0 || h == 0)
4890 r.left = r.top = 0;
4891 r.right = CANON_X_UNIT (f) * f->width;
4892 r.bottom = CANON_Y_UNIT (f) * f->height;
4894 else
4896 r.left = x;
4897 r.top = y;
4898 r.right = x + w;
4899 r.bottom = y + h;
4902 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
4903 expose_window_tree (XWINDOW (f->root_window), &r);
4905 if (WINDOWP (f->tool_bar_window))
4907 struct window *w = XWINDOW (f->tool_bar_window);
4908 RECT window_rect;
4909 RECT intersection_rect;
4910 int window_x, window_y, window_width, window_height;
4912 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
4913 window_rect.left = window_x;
4914 window_rect.top = window_y;
4915 window_rect.right = window_x + window_width;
4916 window_rect.bottom = window_y + window_height;
4918 if (w32_intersect_rectangles (&r, &window_rect, &intersection_rect))
4919 expose_window (w, &intersection_rect);
4924 /* Redraw (parts) of all windows in the window tree rooted at W that
4925 intersect R. R contains frame pixel coordinates. */
4927 static void
4928 expose_window_tree (w, r)
4929 struct window *w;
4930 RECT *r;
4932 while (w)
4934 if (!NILP (w->hchild))
4935 expose_window_tree (XWINDOW (w->hchild), r);
4936 else if (!NILP (w->vchild))
4937 expose_window_tree (XWINDOW (w->vchild), r);
4938 else
4940 RECT window_rect;
4941 RECT intersection_rect;
4942 struct frame *f = XFRAME (w->frame);
4943 int window_x, window_y, window_width, window_height;
4945 /* Frame-relative pixel rectangle of W. */
4946 window_box (w, -1, &window_x, &window_y, &window_width,
4947 &window_height);
4948 window_rect.left
4949 = (window_x
4950 - FRAME_X_LEFT_FLAGS_AREA_WIDTH (f)
4951 - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_Y_UNIT (f));
4952 window_rect.top = window_y;
4953 window_rect.right = window_rect.left
4954 + (window_width
4955 + FRAME_X_FLAGS_AREA_WIDTH (f)
4956 + FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f));
4957 window_rect.bottom = window_rect.top
4958 + window_height + CURRENT_MODE_LINE_HEIGHT (w);
4960 if (w32_intersect_rectangles (r, &window_rect, &intersection_rect))
4961 expose_window (w, &intersection_rect);
4964 w = NILP (w->next) ? 0 : XWINDOW (w->next);
4969 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
4970 which intersects rectangle R. R is in window-relative coordinates. */
4972 static void
4973 expose_area (w, row, r, area)
4974 struct window *w;
4975 struct glyph_row *row;
4976 RECT *r;
4977 enum glyph_row_area area;
4979 int x;
4980 struct glyph *first = row->glyphs[area];
4981 struct glyph *end = row->glyphs[area] + row->used[area];
4982 struct glyph *last;
4983 int first_x;
4985 /* Set x to the window-relative start position for drawing glyphs of
4986 AREA. The first glyph of the text area can be partially visible.
4987 The first glyphs of other areas cannot. */
4988 if (area == LEFT_MARGIN_AREA)
4989 x = 0;
4990 else if (area == TEXT_AREA)
4991 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
4992 else
4993 x = (window_box_width (w, LEFT_MARGIN_AREA)
4994 + window_box_width (w, TEXT_AREA));
4996 if (area == TEXT_AREA && row->fill_line_p)
4997 /* If row extends face to end of line write the whole line. */
4998 x_draw_glyphs (w, x, row, area,
4999 0, row->used[area],
5000 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5001 NULL, NULL, 0);
5002 else
5004 /* Find the first glyph that must be redrawn. */
5005 while (first < end
5006 && x + first->pixel_width < r->left)
5008 x += first->pixel_width;
5009 ++first;
5012 /* Find the last one. */
5013 last = first;
5014 first_x = x;
5015 while (last < end
5016 && x < r->right)
5018 x += last->pixel_width;
5019 ++last;
5022 /* Repaint. */
5023 if (last > first)
5024 x_draw_glyphs (w, first_x, row, area,
5025 first - row->glyphs[area],
5026 last - row->glyphs[area],
5027 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5028 NULL, NULL, 0);
5033 /* Redraw the parts of the glyph row ROW on window W intersecting
5034 rectangle R. R is in window-relative coordinates. */
5036 static void
5037 expose_line (w, row, r)
5038 struct window *w;
5039 struct glyph_row *row;
5040 RECT *r;
5042 xassert (row->enabled_p);
5044 if (row->mode_line_p || w->pseudo_window_p)
5045 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5046 row->inverse_p ? DRAW_INVERSE_VIDEO : DRAW_NORMAL_TEXT,
5047 NULL, NULL, 0);
5048 else
5050 if (row->used[LEFT_MARGIN_AREA])
5051 expose_area (w, row, r, LEFT_MARGIN_AREA);
5052 if (row->used[TEXT_AREA])
5053 expose_area (w, row, r, TEXT_AREA);
5054 if (row->used[RIGHT_MARGIN_AREA])
5055 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5056 x_draw_row_bitmaps (w, row);
5061 /* Return non-zero if W's cursor intersects rectangle R. */
5063 static int
5064 x_phys_cursor_in_rect_p (w, r)
5065 struct window *w;
5066 RECT *r;
5068 RECT cr, result;
5069 struct glyph *cursor_glyph;
5071 cursor_glyph = get_phys_cursor_glyph (w);
5072 if (cursor_glyph)
5074 cr.left = w->phys_cursor.x;
5075 cr.top = w->phys_cursor.y;
5076 cr.right = cr.left + cursor_glyph->pixel_width;
5077 cr.bottom = cr.top + w->phys_cursor_height;
5078 return w32_intersect_rectangles (&cr, r, &result);
5080 else
5081 return 0;
5085 /* Redraw a rectangle of window W. R is a rectangle in window
5086 relative coordinates. Call this function with input blocked. */
5088 static void
5089 expose_window (w, r)
5090 struct window *w;
5091 RECT *r;
5093 struct glyph_row *row;
5094 int y;
5095 int yb = window_text_bottom_y (w);
5096 int cursor_cleared_p;
5098 /* If window is not yet fully initialized, do nothing. This can
5099 happen when toolkit scroll bars are used and a window is split.
5100 Reconfiguring the scroll bar will generate an expose for a newly
5101 created window. */
5102 if (w->current_matrix == NULL)
5103 return;
5105 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5106 r->left, r->top, r->right, r->bottom));
5108 /* Convert to window coordinates. */
5109 r->left = FRAME_TO_WINDOW_PIXEL_X (w, r->left);
5110 r->top = FRAME_TO_WINDOW_PIXEL_Y (w, r->top);
5111 r->right = FRAME_TO_WINDOW_PIXEL_X (w, r->right);
5112 r->bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r->bottom);
5114 /* Turn off the cursor. */
5115 if (!w->pseudo_window_p
5116 && x_phys_cursor_in_rect_p (w, r))
5118 x_clear_cursor (w);
5119 cursor_cleared_p = 1;
5121 else
5122 cursor_cleared_p = 0;
5124 /* Find the first row intersecting the rectangle R. */
5125 row = w->current_matrix->rows;
5126 y = 0;
5127 while (row->enabled_p
5128 && y < yb
5129 && y + row->height < r->top)
5131 y += row->height;
5132 ++row;
5135 /* Display the text in the rectangle, one text line at a time. */
5136 while (row->enabled_p
5137 && y < yb
5138 && y < r->bottom)
5140 expose_line (w, row, r);
5141 y += row->height;
5142 ++row;
5145 /* Display the mode line if there is one. */
5146 if (WINDOW_WANTS_MODELINE_P (w)
5147 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5148 row->enabled_p)
5149 && row->y < r->bottom)
5150 expose_line (w, row, r);
5152 if (!w->pseudo_window_p)
5154 /* Draw border between windows. */
5155 x_draw_vertical_border (w);
5157 /* Turn the cursor on again. */
5158 if (cursor_cleared_p)
5159 x_update_window_cursor (w, 1);
5164 /* Determine the intersection of two rectangles R1 and R2. Return
5165 the intersection in *RESULT. Value is non-zero if RESULT is not
5166 empty. */
5168 static int
5169 w32_intersect_rectangles (r1, r2, result)
5170 RECT *r1, *r2, *result;
5172 RECT *left, *right;
5173 RECT *upper, *lower;
5174 int intersection_p = 0;
5176 /* Arrange so that left is the left-most rectangle. */
5177 if (r1->left < r2->left)
5178 left = r1, right = r2;
5179 else
5180 left = r2, right = r1;
5182 /* X0 of the intersection is right.x0, if this is inside R1,
5183 otherwise there is no intersection. */
5184 if (right->left <= left->right)
5186 result->left = right->left;
5188 /* The right end of the intersection is the minimum of the
5189 the right ends of left and right. */
5190 result->right = min (left->right, right->right);
5192 /* Same game for Y. */
5193 if (r1->top < r2->top)
5194 upper = r1, lower = r2;
5195 else
5196 upper = r2, lower = r1;
5198 /* The upper end of the intersection is lower.y0, if this is inside
5199 of upper. Otherwise, there is no intersection. */
5200 if (lower->top <= upper->bottom)
5202 result->top = lower->top;
5204 /* The lower end of the intersection is the minimum of the lower
5205 ends of upper and lower. */
5206 result->bottom = min (lower->bottom, upper->bottom);
5207 intersection_p = 1;
5211 return intersection_p;
5215 static void
5216 frame_highlight (f)
5217 struct frame *f;
5219 x_update_cursor (f, 1);
5222 static void
5223 frame_unhighlight (f)
5224 struct frame *f;
5226 x_update_cursor (f, 1);
5230 /* The focus has changed. Update the frames as necessary to reflect
5231 the new situation. Note that we can't change the selected frame
5232 here, because the Lisp code we are interrupting might become confused.
5233 Each event gets marked with the frame in which it occurred, so the
5234 Lisp code can tell when the switch took place by examining the events. */
5236 void
5237 x_new_focus_frame (dpyinfo, frame)
5238 struct w32_display_info *dpyinfo;
5239 struct frame *frame;
5241 struct frame *old_focus = dpyinfo->w32_focus_frame;
5243 if (frame != dpyinfo->w32_focus_frame)
5245 /* Set this before calling other routines, so that they see
5246 the correct value of w32_focus_frame. */
5247 dpyinfo->w32_focus_frame = frame;
5249 if (old_focus && old_focus->auto_lower)
5250 x_lower_frame (old_focus);
5252 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
5253 pending_autoraise_frame = dpyinfo->w32_focus_frame;
5254 else
5255 pending_autoraise_frame = 0;
5258 x_frame_rehighlight (dpyinfo);
5261 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5263 void
5264 x_mouse_leave (dpyinfo)
5265 struct w32_display_info *dpyinfo;
5267 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
5270 /* The focus has changed, or we have redirected a frame's focus to
5271 another frame (this happens when a frame uses a surrogate
5272 minibuffer frame). Shift the highlight as appropriate.
5274 The FRAME argument doesn't necessarily have anything to do with which
5275 frame is being highlighted or unhighlighted; we only use it to find
5276 the appropriate display info. */
5277 static void
5278 w32_frame_rehighlight (frame)
5279 struct frame *frame;
5281 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
5284 static void
5285 x_frame_rehighlight (dpyinfo)
5286 struct w32_display_info *dpyinfo;
5288 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
5290 if (dpyinfo->w32_focus_frame)
5292 dpyinfo->w32_highlight_frame
5293 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
5294 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
5295 : dpyinfo->w32_focus_frame);
5296 if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
5298 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
5299 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
5302 else
5303 dpyinfo->w32_highlight_frame = 0;
5305 if (dpyinfo->w32_highlight_frame != old_highlight)
5307 if (old_highlight)
5308 frame_unhighlight (old_highlight);
5309 if (dpyinfo->w32_highlight_frame)
5310 frame_highlight (dpyinfo->w32_highlight_frame);
5314 /* Keyboard processing - modifier keys, etc. */
5316 /* Convert a keysym to its name. */
5318 char *
5319 x_get_keysym_name (keysym)
5320 int keysym;
5322 /* Make static so we can always return it */
5323 static char value[100];
5325 BLOCK_INPUT;
5326 GetKeyNameText(keysym, value, 100);
5327 UNBLOCK_INPUT;
5329 return value;
5332 /* Mouse clicks and mouse movement. Rah. */
5334 /* Given a pixel position (PIX_X, PIX_Y) on the frame F, return
5335 glyph co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle
5336 that the glyph at X, Y occupies, if BOUNDS != 0.
5337 If NOCLIP is nonzero, do not force the value into range. */
5339 void
5340 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
5341 FRAME_PTR f;
5342 register int pix_x, pix_y;
5343 register int *x, *y;
5344 RECT *bounds;
5345 int noclip;
5347 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
5348 if (NILP (Vwindow_system))
5350 *x = pix_x;
5351 *y = pix_y;
5352 return;
5355 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5356 even for negative values. */
5357 if (pix_x < 0)
5358 pix_x -= FONT_WIDTH ((f)->output_data.w32->font) - 1;
5359 if (pix_y < 0)
5360 pix_y -= (f)->output_data.w32->line_height - 1;
5362 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5363 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5365 if (bounds)
5367 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
5368 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
5369 bounds->right = bounds->left + FONT_WIDTH (f->output_data.w32->font) - 1;
5370 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
5373 if (!noclip)
5375 if (pix_x < 0)
5376 pix_x = 0;
5377 else if (pix_x > f->width)
5378 pix_x = f->width;
5380 if (pix_y < 0)
5381 pix_y = 0;
5382 else if (pix_y > f->height)
5383 pix_y = f->height;
5386 *x = pix_x;
5387 *y = pix_y;
5391 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5392 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5393 can't tell the positions because W's display is not up to date,
5394 return 0. */
5397 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
5398 struct window *w;
5399 int hpos, vpos;
5400 int *frame_x, *frame_y;
5402 int success_p;
5404 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
5405 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
5407 if (display_completed)
5409 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
5410 struct glyph *glyph = row->glyphs[TEXT_AREA];
5411 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
5413 *frame_y = row->y;
5414 *frame_x = row->x;
5415 while (glyph < end)
5417 *frame_x += glyph->pixel_width;
5418 ++glyph;
5421 success_p = 1;
5423 else
5425 *frame_y = *frame_x = 0;
5426 success_p = 0;
5429 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
5430 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
5431 return success_p;
5434 BOOL
5435 parse_button (message, pbutton, pup)
5436 int message;
5437 int * pbutton;
5438 int * pup;
5440 int button = 0;
5441 int up = 0;
5443 switch (message)
5445 case WM_LBUTTONDOWN:
5446 button = 0;
5447 up = 0;
5448 break;
5449 case WM_LBUTTONUP:
5450 button = 0;
5451 up = 1;
5452 break;
5453 case WM_MBUTTONDOWN:
5454 if (NILP (Vw32_swap_mouse_buttons))
5455 button = 1;
5456 else
5457 button = 2;
5458 up = 0;
5459 break;
5460 case WM_MBUTTONUP:
5461 if (NILP (Vw32_swap_mouse_buttons))
5462 button = 1;
5463 else
5464 button = 2;
5465 up = 1;
5466 break;
5467 case WM_RBUTTONDOWN:
5468 if (NILP (Vw32_swap_mouse_buttons))
5469 button = 2;
5470 else
5471 button = 1;
5472 up = 0;
5473 break;
5474 case WM_RBUTTONUP:
5475 if (NILP (Vw32_swap_mouse_buttons))
5476 button = 2;
5477 else
5478 button = 1;
5479 up = 1;
5480 break;
5481 default:
5482 return (FALSE);
5485 if (pup) *pup = up;
5486 if (pbutton) *pbutton = button;
5488 return (TRUE);
5492 /* Prepare a mouse-event in *RESULT for placement in the input queue.
5494 If the event is a button press, then note that we have grabbed
5495 the mouse. */
5497 static void
5498 construct_mouse_click (result, msg, f)
5499 struct input_event *result;
5500 W32Msg *msg;
5501 struct frame *f;
5503 int button;
5504 int up;
5506 parse_button (msg->msg.message, &button, &up);
5508 /* Make the event type no_event; we'll change that when we decide
5509 otherwise. */
5510 result->kind = mouse_click;
5511 result->code = button;
5512 result->timestamp = msg->msg.time;
5513 result->modifiers = (msg->dwModifiers
5514 | (up
5515 ? up_modifier
5516 : down_modifier));
5519 int row, column;
5521 XSETINT (result->x, LOWORD (msg->msg.lParam));
5522 XSETINT (result->y, HIWORD (msg->msg.lParam));
5523 XSETFRAME (result->frame_or_window, f);
5527 static void
5528 construct_mouse_wheel (result, msg, f)
5529 struct input_event *result;
5530 W32Msg *msg;
5531 struct frame *f;
5533 POINT p;
5534 result->kind = mouse_wheel;
5535 result->code = (short) HIWORD (msg->msg.wParam);
5536 result->timestamp = msg->msg.time;
5537 result->modifiers = msg->dwModifiers;
5538 p.x = LOWORD (msg->msg.lParam);
5539 p.y = HIWORD (msg->msg.lParam);
5540 ScreenToClient(msg->msg.hwnd, &p);
5541 XSETINT (result->x, p.x);
5542 XSETINT (result->y, p.y);
5543 XSETFRAME (result->frame_or_window, f);
5546 static void
5547 construct_drag_n_drop (result, msg, f)
5548 struct input_event *result;
5549 W32Msg *msg;
5550 struct frame *f;
5552 Lisp_Object files;
5553 Lisp_Object frame;
5554 HDROP hdrop;
5555 POINT p;
5556 WORD num_files;
5557 char *name;
5558 int i, len;
5560 result->kind = drag_n_drop;
5561 result->code = 0;
5562 result->timestamp = msg->msg.time;
5563 result->modifiers = msg->dwModifiers;
5565 hdrop = (HDROP) msg->msg.wParam;
5566 DragQueryPoint (hdrop, &p);
5568 #if 0
5569 p.x = LOWORD (msg->msg.lParam);
5570 p.y = HIWORD (msg->msg.lParam);
5571 ScreenToClient (msg->msg.hwnd, &p);
5572 #endif
5574 XSETINT (result->x, p.x);
5575 XSETINT (result->y, p.y);
5577 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
5578 files = Qnil;
5580 for (i = 0; i < num_files; i++)
5582 len = DragQueryFile (hdrop, i, NULL, 0);
5583 if (len <= 0)
5584 continue;
5585 name = alloca (len + 1);
5586 DragQueryFile (hdrop, i, name, len + 1);
5587 files = Fcons (build_string (name), files);
5590 DragFinish (hdrop);
5592 XSETFRAME (frame, f);
5593 result->frame_or_window = Fcons (frame, files);
5597 /* Function to report a mouse movement to the mainstream Emacs code.
5598 The input handler calls this.
5600 We have received a mouse movement event, which is given in *event.
5601 If the mouse is over a different glyph than it was last time, tell
5602 the mainstream emacs code by setting mouse_moved. If not, ask for
5603 another motion event, so we can check again the next time it moves. */
5605 static MSG last_mouse_motion_event;
5606 static Lisp_Object last_mouse_motion_frame;
5608 static void
5609 note_mouse_movement (frame, msg)
5610 FRAME_PTR frame;
5611 MSG *msg;
5613 last_mouse_movement_time = msg->time;
5614 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
5615 XSETFRAME (last_mouse_motion_frame, frame);
5617 if (msg->hwnd != FRAME_W32_WINDOW (frame))
5619 frame->mouse_moved = 1;
5620 last_mouse_scroll_bar = Qnil;
5621 note_mouse_highlight (frame, -1, -1);
5624 /* Has the mouse moved off the glyph it was on at the last sighting? */
5625 else if (LOWORD (msg->lParam) < last_mouse_glyph.left
5626 || LOWORD (msg->lParam) > last_mouse_glyph.right
5627 || HIWORD (msg->lParam) < last_mouse_glyph.top
5628 || HIWORD (msg->lParam) > last_mouse_glyph.bottom)
5630 frame->mouse_moved = 1;
5631 last_mouse_scroll_bar = Qnil;
5633 note_mouse_highlight (frame, LOWORD (msg->lParam), HIWORD (msg->lParam));
5637 /* This is used for debugging, to turn off note_mouse_highlight. */
5638 int disable_mouse_highlight;
5642 /************************************************************************
5643 Mouse Face
5644 ************************************************************************/
5646 /* Find the glyph under window-relative coordinates X/Y in window W.
5647 Consider only glyphs from buffer text, i.e. no glyphs from overlay
5648 strings. Return in *HPOS and *VPOS the row and column number of
5649 the glyph found. Return in *AREA the glyph area containing X.
5650 Value is a pointer to the glyph found or null if X/Y is not on
5651 text, or we can't tell because W's current matrix is not up to
5652 date. */
5654 static struct glyph *
5655 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area)
5656 struct window *w;
5657 int x, y;
5658 int *hpos, *vpos, *area;
5660 struct glyph *glyph, *end;
5661 struct glyph_row *row;
5662 int x0, i, left_area_width;
5664 /* Find row containing Y. Give up if some row is not enabled. */
5665 for (i = 0; i < w->current_matrix->nrows; ++i)
5667 row = MATRIX_ROW (w->current_matrix, i);
5668 if (!row->enabled_p)
5669 return NULL;
5670 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
5671 break;
5674 *vpos = i;
5675 *hpos = 0;
5677 /* Give up if Y is not in the window. */
5678 if (i == w->current_matrix->nrows)
5679 return NULL;
5681 /* Get the glyph area containing X. */
5682 if (w->pseudo_window_p)
5684 *area = TEXT_AREA;
5685 x0 = 0;
5687 else
5689 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5690 if (x < left_area_width)
5692 *area = LEFT_MARGIN_AREA;
5693 x0 = 0;
5695 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
5697 *area = TEXT_AREA;
5698 x0 = row->x + left_area_width;
5700 else
5702 *area = RIGHT_MARGIN_AREA;
5703 x0 = left_area_width + window_box_width (w, TEXT_AREA);
5707 /* Find glyph containing X. */
5708 glyph = row->glyphs[*area];
5709 end = glyph + row->used[*area];
5710 while (glyph < end)
5712 if (x < x0 + glyph->pixel_width)
5714 if (w->pseudo_window_p)
5715 break;
5716 else if (BUFFERP (glyph->object))
5717 break;
5720 x0 += glyph->pixel_width;
5721 ++glyph;
5724 if (glyph == end)
5725 return NULL;
5727 *hpos = glyph - row->glyphs[*area];
5728 return glyph;
5732 /* Convert frame-relative x/y to coordinates relative to window W.
5733 Takes pseudo-windows into account. */
5735 static void
5736 frame_to_window_pixel_xy (w, x, y)
5737 struct window *w;
5738 int *x, *y;
5740 if (w->pseudo_window_p)
5742 /* A pseudo-window is always full-width, and starts at the
5743 left edge of the frame, plus a frame border. */
5744 struct frame *f = XFRAME (w->frame);
5745 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
5746 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5748 else
5750 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
5751 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
5756 /* Take proper action when mouse has moved to the mode or top line of
5757 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
5758 mode line. X is relative to the start of the text display area of
5759 W, so the width of bitmap areas and scroll bars must be subtracted
5760 to get a position relative to the start of the mode line. */
5762 static void
5763 note_mode_line_highlight (w, x, mode_line_p)
5764 struct window *w;
5765 int x, mode_line_p;
5767 struct frame *f = XFRAME (w->frame);
5768 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5769 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
5770 struct glyph_row *row;
5772 if (mode_line_p)
5773 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
5774 else
5775 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
5777 if (row->enabled_p)
5779 struct glyph *glyph, *end;
5780 Lisp_Object help, map;
5781 int x0;
5783 /* Find the glyph under X. */
5784 glyph = row->glyphs[TEXT_AREA];
5785 end = glyph + row->used[TEXT_AREA];
5786 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
5787 + FRAME_X_LEFT_FLAGS_AREA_WIDTH (f));
5788 while (glyph < end
5789 && x >= x0 + glyph->pixel_width)
5791 x0 += glyph->pixel_width;
5792 ++glyph;
5795 if (glyph < end
5796 && STRINGP (glyph->object)
5797 && XSTRING (glyph->object)->intervals
5798 && glyph->charpos >= 0
5799 && glyph->charpos < XSTRING (glyph->object)->size)
5801 /* If we're on a string with `help-echo' text property,
5802 arrange for the help to be displayed. This is done by
5803 setting the global variable help_echo to the help string. */
5804 help = Fget_text_property (make_number (glyph->charpos),
5805 Qhelp_echo, glyph->object);
5806 if (STRINGP (help))
5807 help_echo = help;
5809 /* Change the mouse pointer according to what is under X/Y. */
5810 map = Fget_text_property (make_number (glyph->charpos),
5811 Qlocal_map, glyph->object);
5812 if (!NILP (Fkeymapp (map)))
5813 cursor = f->output_data.w32->nontext_cursor;
5816 #if 0 /* NTEMACS_TODO: mouse cursor */
5817 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
5818 #endif
5821 /* Take proper action when the mouse has moved to position X, Y on frame F
5822 as regards highlighting characters that have mouse-face properties.
5823 Also dehighlighting chars where the mouse was before.
5824 X and Y can be negative or out of range. */
5826 static void
5827 note_mouse_highlight (f, x, y)
5828 FRAME_PTR f;
5829 int x, y;
5831 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5832 int portion;
5833 Lisp_Object window;
5834 struct window *w;
5836 /* When a menu is active, don't highlight because this looks odd. */
5837 if (popup_activated ())
5838 return;
5840 if (disable_mouse_highlight || !f->glyphs_initialized_p)
5841 return;
5843 dpyinfo->mouse_face_mouse_x = x;
5844 dpyinfo->mouse_face_mouse_y = y;
5845 dpyinfo->mouse_face_mouse_frame = f;
5847 if (dpyinfo->mouse_face_defer)
5848 return;
5850 if (gc_in_progress)
5852 dpyinfo->mouse_face_deferred_gc = 1;
5853 return;
5856 /* Which window is that in? */
5857 window = window_from_coordinates (f, x, y, &portion, 1);
5859 /* If we were displaying active text in another window, clear that. */
5860 if (! EQ (window, dpyinfo->mouse_face_window))
5861 clear_mouse_face (dpyinfo);
5863 /* Not on a window -> return. */
5864 if (!WINDOWP (window))
5865 return;
5867 /* Convert to window-relative pixel coordinates. */
5868 w = XWINDOW (window);
5869 frame_to_window_pixel_xy (w, &x, &y);
5871 /* Handle tool-bar window differently since it doesn't display a
5872 buffer. */
5873 if (EQ (window, f->tool_bar_window))
5875 note_tool_bar_highlight (f, x, y);
5876 return;
5879 if (portion == 1 || portion == 3)
5881 /* Mouse is on the mode or top line. */
5882 note_mode_line_highlight (w, x, portion == 1);
5883 return;
5885 #if 0 /* NTEMACS_TODO: mouse cursor */
5886 else
5887 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5888 f->output_data.x->text_cursor);
5889 #endif
5891 /* Are we in a window whose display is up to date?
5892 And verify the buffer's text has not changed. */
5893 if (/* Within the text portion of the window. */
5894 portion == 0
5895 && EQ (w->window_end_valid, w->buffer)
5896 && w->last_modified == BUF_MODIFF (XBUFFER (w->buffer))
5897 && w->last_overlay_modified == BUF_OVERLAY_MODIFF (XBUFFER (w->buffer)))
5899 int hpos, vpos, pos, i, area;
5900 struct glyph *glyph;
5902 /* Find the glyph under X/Y. */
5903 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area);
5905 /* Clear mouse face if X/Y not over text. */
5906 if (glyph == NULL
5907 || area != TEXT_AREA
5908 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
5910 clear_mouse_face (dpyinfo);
5911 return;
5914 pos = glyph->charpos;
5915 xassert (w->pseudo_window_p || BUFFERP (glyph->object));
5917 /* Check for mouse-face and help-echo. */
5919 Lisp_Object mouse_face, overlay, position;
5920 Lisp_Object *overlay_vec;
5921 int len, noverlays;
5922 struct buffer *obuf;
5923 int obegv, ozv;
5925 /* If we get an out-of-range value, return now; avoid an error. */
5926 if (pos > BUF_Z (XBUFFER (w->buffer)))
5927 return;
5929 /* Make the window's buffer temporarily current for
5930 overlays_at and compute_char_face. */
5931 obuf = current_buffer;
5932 current_buffer = XBUFFER (w->buffer);
5933 obegv = BEGV;
5934 ozv = ZV;
5935 BEGV = BEG;
5936 ZV = Z;
5938 /* Is this char mouse-active or does it have help-echo? */
5939 XSETINT (position, pos);
5941 /* Put all the overlays we want in a vector in overlay_vec.
5942 Store the length in len. If there are more than 10, make
5943 enough space for all, and try again. */
5944 len = 10;
5945 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
5946 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
5947 if (noverlays > len)
5949 len = noverlays;
5950 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
5951 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL);
5954 noverlays = sort_overlays (overlay_vec, noverlays, w);
5956 /* Check mouse-face highlighting. */
5957 if (! (EQ (window, dpyinfo->mouse_face_window)
5958 && vpos >= dpyinfo->mouse_face_beg_row
5959 && vpos <= dpyinfo->mouse_face_end_row
5960 && (vpos > dpyinfo->mouse_face_beg_row
5961 || hpos >= dpyinfo->mouse_face_beg_col)
5962 && (vpos < dpyinfo->mouse_face_end_row
5963 || hpos < dpyinfo->mouse_face_end_col
5964 || dpyinfo->mouse_face_past_end)))
5966 /* Clear the display of the old active region, if any. */
5967 clear_mouse_face (dpyinfo);
5969 /* Find the highest priority overlay that has a mouse-face prop. */
5970 overlay = Qnil;
5971 for (i = 0; i < noverlays; i++)
5973 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
5974 if (!NILP (mouse_face))
5976 overlay = overlay_vec[i];
5977 break;
5981 /* If no overlay applies, get a text property. */
5982 if (NILP (overlay))
5983 mouse_face = Fget_text_property (position, Qmouse_face, w->buffer);
5985 /* Handle the overlay case. */
5986 if (! NILP (overlay))
5988 /* Find the range of text around this char that
5989 should be active. */
5990 Lisp_Object before, after;
5991 int ignore;
5993 before = Foverlay_start (overlay);
5994 after = Foverlay_end (overlay);
5995 /* Record this as the current active region. */
5996 fast_find_position (w, XFASTINT (before),
5997 &dpyinfo->mouse_face_beg_col,
5998 &dpyinfo->mouse_face_beg_row,
5999 &dpyinfo->mouse_face_beg_x,
6000 &dpyinfo->mouse_face_beg_y);
6001 dpyinfo->mouse_face_past_end
6002 = !fast_find_position (w, XFASTINT (after),
6003 &dpyinfo->mouse_face_end_col,
6004 &dpyinfo->mouse_face_end_row,
6005 &dpyinfo->mouse_face_end_x,
6006 &dpyinfo->mouse_face_end_y);
6007 dpyinfo->mouse_face_window = window;
6008 dpyinfo->mouse_face_face_id
6009 = face_at_buffer_position (w, pos, 0, 0,
6010 &ignore, pos + 1, 1);
6012 /* Display it as active. */
6013 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6015 /* Handle the text property case. */
6016 else if (! NILP (mouse_face))
6018 /* Find the range of text around this char that
6019 should be active. */
6020 Lisp_Object before, after, beginning, end;
6021 int ignore;
6023 beginning = Fmarker_position (w->start);
6024 XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
6025 - XFASTINT (w->window_end_pos)));
6026 before
6027 = Fprevious_single_property_change (make_number (pos + 1),
6028 Qmouse_face,
6029 w->buffer, beginning);
6030 after
6031 = Fnext_single_property_change (position, Qmouse_face,
6032 w->buffer, end);
6033 /* Record this as the current active region. */
6034 fast_find_position (w, XFASTINT (before),
6035 &dpyinfo->mouse_face_beg_col,
6036 &dpyinfo->mouse_face_beg_row,
6037 &dpyinfo->mouse_face_beg_x,
6038 &dpyinfo->mouse_face_beg_y);
6039 dpyinfo->mouse_face_past_end
6040 = !fast_find_position (w, XFASTINT (after),
6041 &dpyinfo->mouse_face_end_col,
6042 &dpyinfo->mouse_face_end_row,
6043 &dpyinfo->mouse_face_end_x,
6044 &dpyinfo->mouse_face_end_y);
6045 dpyinfo->mouse_face_window = window;
6046 dpyinfo->mouse_face_face_id
6047 = face_at_buffer_position (w, pos, 0, 0,
6048 &ignore, pos + 1, 1);
6050 /* Display it as active. */
6051 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6055 /* Look for a `help-echo' property. */
6057 Lisp_Object help;
6059 /* Check overlays first. */
6060 help = Qnil;
6061 for (i = 0; i < noverlays && !STRINGP (help); ++i)
6062 help = Foverlay_get (overlay_vec[i], Qhelp_echo);
6064 /* Try text properties. */
6065 if (!STRINGP (help)
6066 && ((STRINGP (glyph->object)
6067 && glyph->charpos >= 0
6068 && glyph->charpos < XSTRING (glyph->object)->size)
6069 || (BUFFERP (glyph->object)
6070 && glyph->charpos >= BEGV
6071 && glyph->charpos < ZV)))
6072 help = Fget_text_property (make_number (glyph->charpos),
6073 Qhelp_echo, glyph->object);
6075 if (STRINGP (help))
6076 help_echo = help;
6079 BEGV = obegv;
6080 ZV = ozv;
6081 current_buffer = obuf;
6087 static void
6088 redo_mouse_highlight ()
6090 if (!NILP (last_mouse_motion_frame)
6091 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6092 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6093 LOWORD (last_mouse_motion_event.lParam),
6094 HIWORD (last_mouse_motion_event.lParam));
6099 /***********************************************************************
6100 Tool-bars
6101 ***********************************************************************/
6103 static int x_tool_bar_item P_ ((struct frame *, int, int,
6104 struct glyph **, int *, int *, int *));
6106 /* Tool-bar item index of the item on which a mouse button was pressed
6107 or -1. */
6109 static int last_tool_bar_item;
6112 /* Get information about the tool-bar item at position X/Y on frame F.
6113 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6114 the current matrix of the tool-bar window of F, or NULL if not
6115 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6116 item in F->current_tool_bar_items. Value is
6118 -1 if X/Y is not on a tool-bar item
6119 0 if X/Y is on the same item that was highlighted before.
6120 1 otherwise. */
6122 static int
6123 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6124 struct frame *f;
6125 int x, y;
6126 struct glyph **glyph;
6127 int *hpos, *vpos, *prop_idx;
6129 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6130 struct window *w = XWINDOW (f->tool_bar_window);
6131 int area;
6133 /* Find the glyph under X/Y. */
6134 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area);
6135 if (*glyph == NULL)
6136 return -1;
6138 /* Get the start of this tool-bar item's properties in
6139 f->current_tool_bar_items. */
6140 if (!tool_bar_item_info (f, *glyph, prop_idx))
6141 return -1;
6143 /* Is mouse on the highlighted item? */
6144 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6145 && *vpos >= dpyinfo->mouse_face_beg_row
6146 && *vpos <= dpyinfo->mouse_face_end_row
6147 && (*vpos > dpyinfo->mouse_face_beg_row
6148 || *hpos >= dpyinfo->mouse_face_beg_col)
6149 && (*vpos < dpyinfo->mouse_face_end_row
6150 || *hpos < dpyinfo->mouse_face_end_col
6151 || dpyinfo->mouse_face_past_end))
6152 return 0;
6154 return 1;
6158 /* Handle mouse button event on the tool_bar of frame F, at
6159 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6160 or ButtonRelase. */
6162 static void
6163 w32_handle_tool_bar_click (f, button_event)
6164 struct frame *f;
6165 struct input_event *button_event;
6167 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6168 struct window *w = XWINDOW (f->tool_bar_window);
6169 int hpos, vpos, prop_idx;
6170 struct glyph *glyph;
6171 Lisp_Object enabled_p;
6172 int x = XFASTINT (button_event->x);
6173 int y = XFASTINT (button_event->y);
6175 /* If not on the highlighted tool-bar item, return. */
6176 frame_to_window_pixel_xy (w, &x, &y);
6177 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6178 return;
6180 /* If item is disabled, do nothing. */
6181 enabled_p = (XVECTOR (f->current_tool_bar_items)
6182 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6183 if (NILP (enabled_p))
6184 return;
6186 if (button_event->kind == mouse_click)
6188 /* Show item in pressed state. */
6189 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
6190 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
6191 last_tool_bar_item = prop_idx;
6193 else
6195 Lisp_Object key, frame;
6196 struct input_event event;
6198 /* Show item in released state. */
6199 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
6200 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
6202 key = (XVECTOR (f->current_tool_bar_items)
6203 ->contents[prop_idx + TOOL_BAR_ITEM_KEY]);
6205 XSETFRAME (frame, f);
6206 event.kind = TOOL_BAR_EVENT;
6207 event.frame_or_window = Fcons (frame, Fcons (Qtool_bar, Qnil));
6208 kbd_buffer_store_event (&event);
6210 event.kind = TOOL_BAR_EVENT;
6211 event.frame_or_window = Fcons (frame, key);
6212 event.modifiers = button_event->modifiers;
6213 kbd_buffer_store_event (&event);
6214 last_tool_bar_item = -1;
6219 /* Possibly highlight a tool_bar item on frame F when mouse moves to
6220 tool-bar window-relative coordinates X/Y. Called from
6221 note_mouse_highlight. */
6223 static void
6224 note_tool_bar_highlight (f, x, y)
6225 struct frame *f;
6226 int x, y;
6228 Lisp_Object window = f->tool_bar_window;
6229 struct window *w = XWINDOW (window);
6230 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6231 int hpos, vpos;
6232 struct glyph *glyph;
6233 struct glyph_row *row;
6234 int i;
6235 Lisp_Object enabled_p;
6236 int prop_idx;
6237 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
6238 int mouse_down_p, rc;
6240 /* Function note_mouse_highlight is called with negative x(y
6241 values when mouse moves outside of the frame. */
6242 if (x <= 0 || y <= 0)
6244 clear_mouse_face (dpyinfo);
6245 return;
6248 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
6249 if (rc < 0)
6251 /* Not on tool-bar item. */
6252 clear_mouse_face (dpyinfo);
6253 return;
6255 else if (rc == 0)
6256 /* On same tool-bar item as before. */
6257 goto set_help_echo;
6259 clear_mouse_face (dpyinfo);
6261 /* Mouse is down, but on different tool-bar item? */
6262 mouse_down_p = (dpyinfo->grabbed
6263 && f == last_mouse_frame
6264 && FRAME_LIVE_P (f));
6265 if (mouse_down_p
6266 && last_tool_bar_item != prop_idx)
6267 return;
6269 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
6270 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
6272 /* If tool-bar item is not enabled, don't highlight it. */
6273 enabled_p = (XVECTOR (f->current_tool_bar_items)
6274 ->contents[prop_idx + TOOL_BAR_ITEM_ENABLED_P]);
6275 if (!NILP (enabled_p))
6277 /* Compute the x-position of the glyph. In front and past the
6278 image is a space. We include this is the highlighted area. */
6279 row = MATRIX_ROW (w->current_matrix, vpos);
6280 for (i = x = 0; i < hpos; ++i)
6281 x += row->glyphs[TEXT_AREA][i].pixel_width;
6283 /* Record this as the current active region. */
6284 dpyinfo->mouse_face_beg_col = hpos;
6285 dpyinfo->mouse_face_beg_row = vpos;
6286 dpyinfo->mouse_face_beg_x = x;
6287 dpyinfo->mouse_face_beg_y = row->y;
6288 dpyinfo->mouse_face_past_end = 0;
6290 dpyinfo->mouse_face_end_col = hpos + 1;
6291 dpyinfo->mouse_face_end_row = vpos;
6292 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
6293 dpyinfo->mouse_face_end_y = row->y;
6294 dpyinfo->mouse_face_window = window;
6295 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
6297 /* Display it as active. */
6298 show_mouse_face (dpyinfo, draw);
6299 dpyinfo->mouse_face_image_state = draw;
6302 set_help_echo:
6304 /* Set help_echo to a help string.to display for this tool-bar item.
6305 w32_read_socket does the rest. */
6306 help_echo = (XVECTOR (f->current_tool_bar_items)
6307 ->contents[prop_idx + TOOL_BAR_ITEM_HELP]);
6308 if (!STRINGP (help_echo))
6309 help_echo = (XVECTOR (f->current_tool_bar_items)
6310 ->contents[prop_idx + TOOL_BAR_ITEM_CAPTION]);
6314 /* Find the glyph matrix position of buffer position POS in window W.
6315 *HPOS, *VPOS, *X, and *Y are set to the positions found. W's
6316 current glyphs must be up to date. If POS is above window start
6317 return (0, 0, 0, 0). If POS is after end of W, return end of
6318 last line in W. */
6320 static int
6321 fast_find_position (w, pos, hpos, vpos, x, y)
6322 struct window *w;
6323 int pos;
6324 int *hpos, *vpos, *x, *y;
6326 int i;
6327 int lastcol;
6328 int maybe_next_line_p = 0;
6329 int line_start_position;
6330 int yb = window_text_bottom_y (w);
6331 struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
6332 struct glyph_row *best_row = row;
6333 int row_vpos = 0, best_row_vpos = 0;
6334 int current_x;
6336 while (row->y < yb)
6338 if (row->used[TEXT_AREA])
6339 line_start_position = row->glyphs[TEXT_AREA]->charpos;
6340 else
6341 line_start_position = 0;
6343 if (line_start_position > pos)
6344 break;
6345 /* If the position sought is the end of the buffer,
6346 don't include the blank lines at the bottom of the window. */
6347 else if (line_start_position == pos
6348 && pos == BUF_ZV (XBUFFER (w->buffer)))
6350 maybe_next_line_p = 1;
6351 break;
6353 else if (line_start_position > 0)
6355 best_row = row;
6356 best_row_vpos = row_vpos;
6359 ++row;
6360 ++row_vpos;
6363 /* Find the right column within BEST_ROW. */
6364 lastcol = 0;
6365 current_x = best_row->x;
6366 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
6368 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
6369 int charpos;
6371 charpos = glyph->charpos;
6372 if (charpos == pos)
6374 *hpos = i;
6375 *vpos = best_row_vpos;
6376 *x = current_x;
6377 *y = best_row->y;
6378 return 1;
6380 else if (charpos > pos)
6381 break;
6382 else if (charpos > 0)
6383 lastcol = i;
6385 current_x += glyph->pixel_width;
6388 /* If we're looking for the end of the buffer,
6389 and we didn't find it in the line we scanned,
6390 use the start of the following line. */
6391 if (maybe_next_line_p)
6393 ++best_row;
6394 ++best_row_vpos;
6395 lastcol = 0;
6396 current_x = best_row->x;
6399 *vpos = best_row_vpos;
6400 *hpos = lastcol + 1;
6401 *x = current_x;
6402 *y = best_row->y;
6403 return 0;
6407 /* Display the active region described by mouse_face_*
6408 in its mouse-face if HL > 0, in its normal face if HL = 0. */
6410 static void
6411 show_mouse_face (dpyinfo, draw)
6412 struct w32_display_info *dpyinfo;
6413 enum draw_glyphs_face draw;
6415 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
6416 struct frame *f = XFRAME (WINDOW_FRAME (w));
6417 int i;
6418 int cursor_off_p = 0;
6419 struct cursor_pos saved_cursor;
6421 saved_cursor = output_cursor;
6423 /* If window is in the process of being destroyed, don't bother
6424 to do anything. */
6425 if (w->current_matrix == NULL)
6426 goto set_x_cursor;
6428 /* Recognize when we are called to operate on rows that don't exist
6429 anymore. This can happen when a window is split. */
6430 if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
6431 goto set_x_cursor;
6433 set_output_cursor (&w->phys_cursor);
6435 /* Note that mouse_face_beg_row etc. are window relative. */
6436 for (i = dpyinfo->mouse_face_beg_row;
6437 i <= dpyinfo->mouse_face_end_row;
6438 i++)
6440 int start_hpos, end_hpos, start_x;
6441 struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
6443 /* Don't do anything if row doesn't have valid contents. */
6444 if (!row->enabled_p)
6445 continue;
6447 /* For all but the first row, the highlight starts at column 0. */
6448 if (i == dpyinfo->mouse_face_beg_row)
6450 start_hpos = dpyinfo->mouse_face_beg_col;
6451 start_x = dpyinfo->mouse_face_beg_x;
6453 else
6455 start_hpos = 0;
6456 start_x = 0;
6459 if (i == dpyinfo->mouse_face_end_row)
6460 end_hpos = dpyinfo->mouse_face_end_col;
6461 else
6462 end_hpos = row->used[TEXT_AREA];
6464 /* If the cursor's in the text we are about to rewrite, turn the
6465 cursor off. */
6466 if (!w->pseudo_window_p
6467 && i == output_cursor.vpos
6468 && output_cursor.hpos >= start_hpos - 1
6469 && output_cursor.hpos <= end_hpos)
6471 x_update_window_cursor (w, 0);
6472 cursor_off_p = 1;
6475 if (end_hpos > start_hpos)
6476 x_draw_glyphs (w, start_x, row, TEXT_AREA,
6477 start_hpos, end_hpos, draw, NULL, NULL, 0);
6480 /* If we turned the cursor off, turn it back on. */
6481 if (cursor_off_p)
6482 x_display_cursor (w, 1,
6483 output_cursor.hpos, output_cursor.vpos,
6484 output_cursor.x, output_cursor.y);
6486 output_cursor = saved_cursor;
6488 set_x_cursor:
6489 #if 0 /* NTEMACS_TODO: mouse cursor */
6490 /* Change the mouse cursor. */
6491 if (draw == DRAW_NORMAL_TEXT)
6492 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6493 f->output_data.x->text_cursor);
6494 else if (draw == DRAW_MOUSE_FACE)
6495 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6496 f->output_data.x->cross_cursor);
6497 else
6498 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
6499 f->output_data.x->nontext_cursor);
6500 #endif
6505 /* Clear out the mouse-highlighted active region.
6506 Redraw it unhighlighted first. */
6508 void
6509 clear_mouse_face (dpyinfo)
6510 struct w32_display_info *dpyinfo;
6512 if (tip_frame)
6513 return;
6515 if (! NILP (dpyinfo->mouse_face_window))
6516 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
6518 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6519 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6520 dpyinfo->mouse_face_window = Qnil;
6523 /* Just discard the mouse face information for frame F, if any.
6524 This is used when the size of F is changed. */
6526 void
6527 cancel_mouse_face (f)
6528 FRAME_PTR f;
6530 Lisp_Object window;
6531 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6533 window = dpyinfo->mouse_face_window;
6534 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
6536 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
6537 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
6538 dpyinfo->mouse_face_window = Qnil;
6542 struct scroll_bar *x_window_to_scroll_bar ();
6543 static void x_scroll_bar_report_motion ();
6545 /* Return the current position of the mouse.
6546 *fp should be a frame which indicates which display to ask about.
6548 If the mouse movement started in a scroll bar, set *fp, *bar_window,
6549 and *part to the frame, window, and scroll bar part that the mouse
6550 is over. Set *x and *y to the portion and whole of the mouse's
6551 position on the scroll bar.
6553 If the mouse movement started elsewhere, set *fp to the frame the
6554 mouse is on, *bar_window to nil, and *x and *y to the character cell
6555 the mouse is over.
6557 Set *time to the server timestamp for the time at which the mouse
6558 was at this position.
6560 Don't store anything if we don't have a valid set of values to report.
6562 This clears the mouse_moved flag, so we can wait for the next mouse
6563 movement. This also calls XQueryPointer, which will cause the
6564 server to give us another MotionNotify when the mouse moves
6565 again. */
6567 static void
6568 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
6569 FRAME_PTR *fp;
6570 int insist;
6571 Lisp_Object *bar_window;
6572 enum scroll_bar_part *part;
6573 Lisp_Object *x, *y;
6574 unsigned long *time;
6576 FRAME_PTR f1;
6578 BLOCK_INPUT;
6580 if (! NILP (last_mouse_scroll_bar) && insist == 0)
6581 /* This is never called at the moment. */
6582 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
6583 else
6585 POINT pt;
6587 Lisp_Object frame, tail;
6589 /* Clear the mouse-moved flag for every frame on this display. */
6590 FOR_EACH_FRAME (tail, frame)
6591 XFRAME (frame)->mouse_moved = 0;
6593 last_mouse_scroll_bar = Qnil;
6595 GetCursorPos (&pt);
6597 /* Now we have a position on the root; find the innermost window
6598 containing the pointer. */
6600 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
6601 && FRAME_LIVE_P (last_mouse_frame))
6603 /* If mouse was grabbed on a frame, give coords for that frame
6604 even if the mouse is now outside it. */
6605 f1 = last_mouse_frame;
6607 else
6609 /* Is window under mouse one of our frames? */
6610 f1 = x_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp), WindowFromPoint(pt));
6613 /* If not, is it one of our scroll bars? */
6614 if (! f1)
6616 struct scroll_bar *bar = x_window_to_scroll_bar (WindowFromPoint(pt));
6618 if (bar)
6620 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6624 if (f1 == 0 && insist > 0)
6625 f1 = SELECTED_FRAME ();
6627 if (f1)
6629 /* Ok, we found a frame. Store all the values.
6630 last_mouse_glyph is a rectangle used to reduce the
6631 generation of mouse events. To not miss any motion
6632 events, we must divide the frame into rectangles of the
6633 size of the smallest character that could be displayed
6634 on it, i.e. into the same rectangles that matrices on
6635 the frame are divided into. */
6637 #if OLD_REDISPLAY_CODE
6638 int ignore1, ignore2;
6640 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
6642 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
6643 &last_mouse_glyph,
6644 FRAME_W32_DISPLAY_INFO (f1)->grabbed
6645 || insist);
6646 #else
6647 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
6649 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
6650 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
6651 int x = pt.x;
6652 int y = pt.y;
6654 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
6655 round down even for negative values. */
6656 if (x < 0)
6657 x -= width - 1;
6658 if (y < 0)
6659 y -= height - 1;
6661 last_mouse_glyph.left = (x + width - 1) / width * width;
6662 last_mouse_glyph.top = (y + height - 1) / height * height;
6663 last_mouse_glyph.right = last_mouse_glyph.left + width;
6664 last_mouse_glyph.bottom = last_mouse_glyph.top + height;
6666 #endif
6668 *bar_window = Qnil;
6669 *part = 0;
6670 *fp = f1;
6671 XSETINT (*x, pt.x);
6672 XSETINT (*y, pt.y);
6673 *time = last_mouse_movement_time;
6678 UNBLOCK_INPUT;
6682 /* Scroll bar support. */
6684 /* Given an window ID, find the struct scroll_bar which manages it.
6685 This can be called in GC, so we have to make sure to strip off mark
6686 bits. */
6687 struct scroll_bar *
6688 x_window_to_scroll_bar (window_id)
6689 Window window_id;
6691 Lisp_Object tail;
6693 for (tail = Vframe_list;
6694 XGCTYPE (tail) == Lisp_Cons;
6695 tail = XCDR (tail))
6697 Lisp_Object frame, bar, condemned;
6699 frame = XCAR (tail);
6700 /* All elements of Vframe_list should be frames. */
6701 if (! GC_FRAMEP (frame))
6702 abort ();
6704 /* Scan this frame's scroll bar list for a scroll bar with the
6705 right window ID. */
6706 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
6707 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
6708 /* This trick allows us to search both the ordinary and
6709 condemned scroll bar lists with one loop. */
6710 ! GC_NILP (bar) || (bar = condemned,
6711 condemned = Qnil,
6712 ! GC_NILP (bar));
6713 bar = XSCROLL_BAR (bar)->next)
6714 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
6715 return XSCROLL_BAR (bar);
6718 return 0;
6723 /* Set the thumb size and position of scroll bar BAR. We are currently
6724 displaying PORTION out of a whole WHOLE, and our position POSITION. */
6726 static void
6727 w32_set_scroll_bar_thumb (bar, portion, position, whole)
6728 struct scroll_bar *bar;
6729 int portion, position, whole;
6731 Window w = SCROLL_BAR_W32_WINDOW (bar);
6732 int range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
6733 int sb_page, sb_pos;
6734 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
6736 if (whole)
6738 /* Position scroll bar at rock bottom if the bottom of the
6739 buffer is visible. This avoids shinking the thumb away
6740 to nothing if it is held at the bottom of the buffer. */
6741 if (position + portion >= whole)
6743 sb_page = range * (whole - position) / whole
6744 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6745 sb_pos = range;
6748 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6749 sb_pos = position * range / whole;
6751 else
6753 sb_page = range;
6754 sb_pos = 0;
6757 BLOCK_INPUT;
6759 if (pfnSetScrollInfo)
6761 SCROLLINFO si;
6763 si.cbSize = sizeof (si);
6764 /* Only update page size if currently dragging, to reduce
6765 flicker effects. */
6766 if (draggingp)
6767 si.fMask = SIF_PAGE;
6768 else
6769 si.fMask = SIF_PAGE | SIF_POS;
6770 si.nPage = sb_page;
6771 si.nPos = sb_pos;
6773 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
6775 else
6776 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
6778 UNBLOCK_INPUT;
6782 /************************************************************************
6783 Scroll bars, general
6784 ************************************************************************/
6786 HWND
6787 my_create_scrollbar (f, bar)
6788 struct frame * f;
6789 struct scroll_bar * bar;
6791 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
6792 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
6793 (LPARAM) bar);
6796 //#define ATTACH_THREADS
6798 BOOL
6799 my_show_window (FRAME_PTR f, HWND hwnd, int how)
6801 #ifndef ATTACH_THREADS
6802 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
6803 (WPARAM) hwnd, (LPARAM) how);
6804 #else
6805 return ShowWindow (hwnd, how);
6806 #endif
6809 void
6810 my_set_window_pos (HWND hwnd, HWND hwndAfter,
6811 int x, int y, int cx, int cy, UINT flags)
6813 #ifndef ATTACH_THREADS
6814 WINDOWPOS pos;
6815 pos.hwndInsertAfter = hwndAfter;
6816 pos.x = x;
6817 pos.y = y;
6818 pos.cx = cx;
6819 pos.cy = cy;
6820 pos.flags = flags;
6821 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
6822 #else
6823 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
6824 #endif
6827 BOOL
6828 my_set_focus (f, hwnd)
6829 struct frame * f;
6830 HWND hwnd;
6832 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
6833 (WPARAM) hwnd, 0);
6836 BOOL
6837 my_set_foreground_window (hwnd)
6838 HWND hwnd;
6840 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
6843 void
6844 my_destroy_window (f, hwnd)
6845 struct frame * f;
6846 HWND hwnd;
6848 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
6849 (WPARAM) hwnd, 0);
6852 /* Create a scroll bar and return the scroll bar vector for it. W is
6853 the Emacs window on which to create the scroll bar. TOP, LEFT,
6854 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
6855 scroll bar. */
6857 static struct scroll_bar *
6858 x_scroll_bar_create (w, top, left, width, height)
6859 struct window *w;
6860 int top, left, width, height;
6862 struct frame *f = XFRAME (WINDOW_FRAME (w));
6863 HWND hwnd;
6864 struct scroll_bar *bar
6865 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
6867 BLOCK_INPUT;
6869 XSETWINDOW (bar->window, w);
6870 XSETINT (bar->top, top);
6871 XSETINT (bar->left, left);
6872 XSETINT (bar->width, width);
6873 XSETINT (bar->height, height);
6874 XSETINT (bar->start, 0);
6875 XSETINT (bar->end, 0);
6876 bar->dragging = Qnil;
6878 /* Requires geometry to be set before call to create the real window */
6880 hwnd = my_create_scrollbar (f, bar);
6882 if (pfnSetScrollInfo)
6884 SCROLLINFO si;
6886 si.cbSize = sizeof (si);
6887 si.fMask = SIF_ALL;
6888 si.nMin = 0;
6889 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
6890 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
6891 si.nPage = si.nMax;
6892 si.nPos = 0;
6894 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
6896 else
6898 SetScrollRange (hwnd, SB_CTL, 0,
6899 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
6900 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
6903 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
6905 /* Add bar to its frame's list of scroll bars. */
6906 bar->next = FRAME_SCROLL_BARS (f);
6907 bar->prev = Qnil;
6908 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
6909 if (! NILP (bar->next))
6910 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
6912 UNBLOCK_INPUT;
6914 return bar;
6918 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
6919 nil. */
6921 static void
6922 x_scroll_bar_remove (bar)
6923 struct scroll_bar *bar;
6925 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
6927 BLOCK_INPUT;
6929 /* Destroy the window. */
6930 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
6932 /* Disassociate this scroll bar from its window. */
6933 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
6935 UNBLOCK_INPUT;
6938 /* Set the handle of the vertical scroll bar for WINDOW to indicate
6939 that we are displaying PORTION characters out of a total of WHOLE
6940 characters, starting at POSITION. If WINDOW has no scroll bar,
6941 create one. */
6942 static void
6943 w32_set_vertical_scroll_bar (w, portion, whole, position)
6944 struct window *w;
6945 int portion, whole, position;
6947 struct frame *f = XFRAME (w->frame);
6948 struct scroll_bar *bar;
6949 int top, left, sb_left, width, sb_width, height;
6950 int window_x, window_y, window_width, window_height;
6952 /* Get window dimensions. */
6953 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
6954 top = window_y;
6955 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
6956 height = window_height;
6958 /* Compute the left edge of the scroll bar area. */
6959 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
6960 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
6961 else
6962 left = XFASTINT (w->left);
6963 left *= CANON_X_UNIT (f);
6964 left += FRAME_INTERNAL_BORDER_WIDTH (f);
6966 /* Compute the width of the scroll bar which might be less than
6967 the width of the area reserved for the scroll bar. */
6968 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
6969 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
6970 else
6971 sb_width = width;
6973 /* Compute the left edge of the scroll bar. */
6974 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
6975 sb_left = left + width - sb_width - (width - sb_width) / 2;
6976 else
6977 sb_left = left + (width - sb_width) / 2;
6979 /* Does the scroll bar exist yet? */
6980 if (NILP (w->vertical_scroll_bar))
6982 HDC hdc;
6983 BLOCK_INPUT;
6984 hdc = get_frame_dc (f);
6985 w32_clear_area (f, hdc, left, top, width, height);
6986 release_frame_dc (f, hdc);
6987 UNBLOCK_INPUT;
6989 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
6991 else
6993 /* It may just need to be moved and resized. */
6994 HWND hwnd;
6996 bar = XSCROLL_BAR (w->vertical_scroll_bar);
6997 hwnd = SCROLL_BAR_W32_WINDOW (bar);
6999 /* If already correctly positioned, do nothing. */
7000 if ( XINT (bar->left) == sb_left
7001 && XINT (bar->top) == top
7002 && XINT (bar->width) == sb_width
7003 && XINT (bar->height) == height )
7005 /* Redraw after clear_frame. */
7006 if (!my_show_window (f, hwnd, SW_NORMAL))
7007 InvalidateRect (hwnd, NULL, FALSE);
7009 else
7011 HDC hdc;
7012 BLOCK_INPUT;
7014 hdc = get_frame_dc (f);
7015 /* Since Windows scroll bars are smaller than the space reserved
7016 for them on the frame, we have to clear "under" them. */
7017 w32_clear_area (f, hdc,
7018 left,
7019 top,
7020 width,
7021 height);
7022 release_frame_dc (f, hdc);
7024 /* Make sure scroll bar is "visible" before moving, to ensure the
7025 area of the parent window now exposed will be refreshed. */
7026 my_show_window (f, hwnd, SW_HIDE);
7027 MoveWindow (hwnd, sb_left, top,
7028 sb_width, height, TRUE);
7029 if (pfnSetScrollInfo)
7031 SCROLLINFO si;
7033 si.cbSize = sizeof (si);
7034 si.fMask = SIF_RANGE;
7035 si.nMin = 0;
7036 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
7037 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7039 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
7041 else
7042 SetScrollRange (hwnd, SB_CTL, 0,
7043 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
7044 my_show_window (f, hwnd, SW_NORMAL);
7045 // InvalidateRect (w, NULL, FALSE);
7047 /* Remember new settings. */
7048 XSETINT (bar->left, sb_left);
7049 XSETINT (bar->top, top);
7050 XSETINT (bar->width, sb_width);
7051 XSETINT (bar->height, height);
7053 UNBLOCK_INPUT;
7056 w32_set_scroll_bar_thumb (bar, portion, position, whole);
7058 XSETVECTOR (w->vertical_scroll_bar, bar);
7062 /* The following three hooks are used when we're doing a thorough
7063 redisplay of the frame. We don't explicitly know which scroll bars
7064 are going to be deleted, because keeping track of when windows go
7065 away is a real pain - "Can you say set-window-configuration, boys
7066 and girls?" Instead, we just assert at the beginning of redisplay
7067 that *all* scroll bars are to be removed, and then save a scroll bar
7068 from the fiery pit when we actually redisplay its window. */
7070 /* Arrange for all scroll bars on FRAME to be removed at the next call
7071 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
7072 `*redeem_scroll_bar_hook' is applied to its window before the judgement. */
7073 static void
7074 w32_condemn_scroll_bars (frame)
7075 FRAME_PTR frame;
7077 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
7078 while (! NILP (FRAME_SCROLL_BARS (frame)))
7080 Lisp_Object bar;
7081 bar = FRAME_SCROLL_BARS (frame);
7082 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
7083 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
7084 XSCROLL_BAR (bar)->prev = Qnil;
7085 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
7086 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
7087 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
7091 /* Unmark WINDOW's scroll bar for deletion in this judgement cycle.
7092 Note that WINDOW isn't necessarily condemned at all. */
7093 static void
7094 w32_redeem_scroll_bar (window)
7095 struct window *window;
7097 struct scroll_bar *bar;
7099 /* We can't redeem this window's scroll bar if it doesn't have one. */
7100 if (NILP (window->vertical_scroll_bar))
7101 abort ();
7103 bar = XSCROLL_BAR (window->vertical_scroll_bar);
7105 /* Unlink it from the condemned list. */
7107 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
7109 if (NILP (bar->prev))
7111 /* If the prev pointer is nil, it must be the first in one of
7112 the lists. */
7113 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
7114 /* It's not condemned. Everything's fine. */
7115 return;
7116 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
7117 window->vertical_scroll_bar))
7118 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
7119 else
7120 /* If its prev pointer is nil, it must be at the front of
7121 one or the other! */
7122 abort ();
7124 else
7125 XSCROLL_BAR (bar->prev)->next = bar->next;
7127 if (! NILP (bar->next))
7128 XSCROLL_BAR (bar->next)->prev = bar->prev;
7130 bar->next = FRAME_SCROLL_BARS (f);
7131 bar->prev = Qnil;
7132 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7133 if (! NILP (bar->next))
7134 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7138 /* Remove all scroll bars on FRAME that haven't been saved since the
7139 last call to `*condemn_scroll_bars_hook'. */
7140 static void
7141 w32_judge_scroll_bars (f)
7142 FRAME_PTR f;
7144 Lisp_Object bar, next;
7146 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
7148 /* Clear out the condemned list now so we won't try to process any
7149 more events on the hapless scroll bars. */
7150 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
7152 for (; ! NILP (bar); bar = next)
7154 struct scroll_bar *b = XSCROLL_BAR (bar);
7156 x_scroll_bar_remove (b);
7158 next = b->next;
7159 b->next = b->prev = Qnil;
7162 /* Now there should be no references to the condemned scroll bars,
7163 and they should get garbage-collected. */
7166 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
7167 is set to something other than no_event, it is enqueued.
7169 This may be called from a signal handler, so we have to ignore GC
7170 mark bits. */
7172 static int
7173 x_scroll_bar_handle_click (bar, msg, emacs_event)
7174 struct scroll_bar *bar;
7175 W32Msg *msg;
7176 struct input_event *emacs_event;
7178 if (! GC_WINDOWP (bar->window))
7179 abort ();
7181 emacs_event->kind = w32_scroll_bar_click;
7182 emacs_event->code = 0;
7183 /* not really meaningful to distinguish up/down */
7184 emacs_event->modifiers = msg->dwModifiers;
7185 emacs_event->frame_or_window = bar->window;
7186 emacs_event->timestamp = msg->msg.time;
7189 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7190 int y;
7191 int dragging = !NILP (bar->dragging);
7193 if (pfnGetScrollInfo)
7195 SCROLLINFO si;
7197 si.cbSize = sizeof (si);
7198 si.fMask = SIF_POS;
7200 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
7201 y = si.nPos;
7203 else
7204 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
7206 bar->dragging = Qnil;
7208 switch (LOWORD (msg->msg.wParam))
7210 case SB_LINEDOWN:
7211 emacs_event->part = scroll_bar_down_arrow;
7212 break;
7213 case SB_LINEUP:
7214 emacs_event->part = scroll_bar_up_arrow;
7215 break;
7216 case SB_PAGEUP:
7217 emacs_event->part = scroll_bar_above_handle;
7218 break;
7219 case SB_PAGEDOWN:
7220 emacs_event->part = scroll_bar_below_handle;
7221 break;
7222 case SB_TOP:
7223 emacs_event->part = scroll_bar_handle;
7224 y = 0;
7225 break;
7226 case SB_BOTTOM:
7227 emacs_event->part = scroll_bar_handle;
7228 y = top_range;
7229 break;
7230 case SB_THUMBTRACK:
7231 case SB_THUMBPOSITION:
7232 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
7233 y = HIWORD (msg->msg.wParam);
7234 bar->dragging = Qt;
7235 emacs_event->part = scroll_bar_handle;
7237 /* "Silently" update current position. */
7238 if (pfnSetScrollInfo)
7240 SCROLLINFO si;
7242 si.cbSize = sizeof (si);
7243 si.fMask = SIF_POS;
7244 si.nPos = y;
7245 /* Remember apparent position (we actually lag behind the real
7246 position, so don't set that directly. */
7247 last_scroll_bar_drag_pos = y;
7249 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
7251 else
7252 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
7253 break;
7254 case SB_ENDSCROLL:
7255 /* If this is the end of a drag sequence, then reset the scroll
7256 handle size to normal and do a final redraw. Otherwise do
7257 nothing. */
7258 if (dragging)
7260 if (pfnSetScrollInfo)
7262 SCROLLINFO si;
7263 int start = XINT (bar->start);
7264 int end = XINT (bar->end);
7266 si.cbSize = sizeof (si);
7267 si.fMask = SIF_PAGE | SIF_POS;
7268 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7269 si.nPos = last_scroll_bar_drag_pos;
7270 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
7272 else
7273 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
7275 /* fall through */
7276 default:
7277 emacs_event->kind = no_event;
7278 return FALSE;
7281 XSETINT (emacs_event->x, y);
7282 XSETINT (emacs_event->y, top_range);
7284 return TRUE;
7288 /* Return information to the user about the current position of the mouse
7289 on the scroll bar. */
7290 static void
7291 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
7292 FRAME_PTR *fp;
7293 Lisp_Object *bar_window;
7294 enum scroll_bar_part *part;
7295 Lisp_Object *x, *y;
7296 unsigned long *time;
7298 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
7299 Window w = SCROLL_BAR_W32_WINDOW (bar);
7300 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7301 int pos;
7302 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7304 BLOCK_INPUT;
7306 *fp = f;
7307 *bar_window = bar->window;
7309 if (pfnGetScrollInfo)
7311 SCROLLINFO si;
7313 si.cbSize = sizeof (si);
7314 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
7316 pfnGetScrollInfo (w, SB_CTL, &si);
7317 pos = si.nPos;
7318 top_range = si.nMax - si.nPage + 1;
7320 else
7321 pos = GetScrollPos (w, SB_CTL);
7323 switch (LOWORD (last_mouse_scroll_bar_pos))
7325 case SB_THUMBPOSITION:
7326 case SB_THUMBTRACK:
7327 *part = scroll_bar_handle;
7328 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
7329 pos = HIWORD (last_mouse_scroll_bar_pos);
7330 break;
7331 case SB_LINEDOWN:
7332 *part = scroll_bar_handle;
7333 pos++;
7334 break;
7335 default:
7336 *part = scroll_bar_handle;
7337 break;
7340 XSETINT(*x, pos);
7341 XSETINT(*y, top_range);
7343 f->mouse_moved = 0;
7344 last_mouse_scroll_bar = Qnil;
7346 *time = last_mouse_movement_time;
7348 UNBLOCK_INPUT;
7351 /* The screen has been cleared so we may have changed foreground or
7352 background colors, and the scroll bars may need to be redrawn.
7353 Clear out the scroll bars, and ask for expose events, so we can
7354 redraw them. */
7355 void
7356 x_scroll_bar_clear (f)
7357 struct frame *f;
7359 Lisp_Object bar;
7361 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
7362 bar = XSCROLL_BAR (bar)->next)
7364 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
7365 HDC hdc = GetDC (window);
7366 RECT rect;
7368 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
7369 arranges to refresh the scroll bar if hidden. */
7370 my_show_window (f, window, SW_HIDE);
7372 GetClientRect (window, &rect);
7373 select_palette (f, hdc);
7374 w32_clear_rect (f, hdc, &rect);
7375 deselect_palette (f, hdc);
7377 ReleaseDC (window, hdc);
7381 show_scroll_bars (f, how)
7382 FRAME_PTR f;
7383 int how;
7385 Lisp_Object bar;
7387 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
7388 bar = XSCROLL_BAR (bar)->next)
7390 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
7391 my_show_window (f, window, how);
7396 /* The main W32 event-reading loop - w32_read_socket. */
7398 /* Timestamp of enter window event. This is only used by w32_read_socket,
7399 but we have to put it out here, since static variables within functions
7400 sometimes don't work. */
7401 static Time enter_timestamp;
7403 /* Record the last 100 characters stored
7404 to help debug the loss-of-chars-during-GC problem. */
7405 int temp_index;
7406 short temp_buffer[100];
7409 /* Read events coming from the W32 shell.
7410 This routine is called by the SIGIO handler.
7411 We return as soon as there are no more events to be read.
7413 Events representing keys are stored in buffer BUFP,
7414 which can hold up to NUMCHARS characters.
7415 We return the number of characters stored into the buffer,
7416 thus pretending to be `read'.
7418 EXPECTED is nonzero if the caller knows input is available.
7420 Some of these messages are reposted back to the message queue since the
7421 system calls the windows proc directly in a context where we cannot return
7422 the data nor can we guarantee the state we are in. So if we dispatch them
7423 we will get into an infinite loop. To prevent this from ever happening we
7424 will set a variable to indicate we are in the read_socket call and indicate
7425 which message we are processing since the windows proc gets called
7426 recursively with different messages by the system.
7430 w32_read_socket (sd, bufp, numchars, expected)
7431 register int sd;
7432 register struct input_event *bufp;
7433 register int numchars;
7434 int expected;
7436 int count = 0;
7437 int check_visibility = 0;
7438 W32Msg msg;
7439 struct frame *f;
7440 struct w32_display_info *dpyinfo = &one_w32_display_info;
7442 if (interrupt_input_blocked)
7444 interrupt_input_pending = 1;
7445 return -1;
7448 interrupt_input_pending = 0;
7449 BLOCK_INPUT;
7451 /* So people can tell when we have read the available input. */
7452 input_signal_count++;
7454 if (numchars <= 0)
7455 abort (); /* Don't think this happens. */
7457 /* NTEMACS_TODO: tooltips, tool-bars, ghostscript integration, mouse
7458 cursors. */
7459 while (get_next_msg (&msg, FALSE))
7461 switch (msg.msg.message)
7463 case WM_PAINT:
7464 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7466 if (f)
7468 if (msg.rect.right == msg.rect.left ||
7469 msg.rect.bottom == msg.rect.top)
7471 /* We may get paint messages even though the client
7472 area is clipped - these are not expose events. */
7473 DebPrint (("clipped frame %04x (%s) got WM_PAINT\n", f,
7474 XSTRING (f->name)->data));
7476 else if (f->async_visible != 1)
7478 /* Definitely not obscured, so mark as visible. */
7479 f->async_visible = 1;
7480 f->async_iconified = 0;
7481 SET_FRAME_GARBAGED (f);
7482 DebPrint (("frame %04x (%s) reexposed\n", f,
7483 XSTRING (f->name)->data));
7485 /* WM_PAINT serves as MapNotify as well, so report
7486 visibility changes properly. */
7487 if (f->iconified)
7489 bufp->kind = deiconify_event;
7490 XSETFRAME (bufp->frame_or_window, f);
7491 bufp++;
7492 count++;
7493 numchars--;
7495 else if (! NILP(Vframe_list)
7496 && ! NILP (XCDR (Vframe_list)))
7497 /* Force a redisplay sooner or later to update the
7498 frame titles in case this is the second frame. */
7499 record_asynch_buffer_change ();
7501 else
7503 HDC hdc = get_frame_dc (f);
7505 /* Erase background again for safety. */
7506 w32_clear_rect (f, hdc, &msg.rect);
7507 release_frame_dc (f, hdc);
7508 expose_frame (f,
7509 msg.rect.left,
7510 msg.rect.top,
7511 msg.rect.right - msg.rect.left,
7512 msg.rect.bottom - msg.rect.top);
7515 break;
7517 case WM_INPUTLANGCHANGE:
7518 /* Generate a language change event. */
7519 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7521 if (f)
7523 if (numchars == 0)
7524 abort ();
7526 bufp->kind = language_change_event;
7527 XSETFRAME (bufp->frame_or_window, f);
7528 bufp->code = msg.msg.wParam;
7529 bufp->modifiers = msg.msg.lParam & 0xffff;
7530 bufp++;
7531 count++;
7532 numchars--;
7534 break;
7536 case WM_KEYDOWN:
7537 case WM_SYSKEYDOWN:
7538 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7540 if (f && !f->iconified)
7542 if (temp_index == sizeof temp_buffer / sizeof (short))
7543 temp_index = 0;
7544 temp_buffer[temp_index++] = msg.msg.wParam;
7545 bufp->kind = non_ascii_keystroke;
7546 bufp->code = msg.msg.wParam;
7547 bufp->modifiers = msg.dwModifiers;
7548 XSETFRAME (bufp->frame_or_window, f);
7549 bufp->timestamp = msg.msg.time;
7550 bufp++;
7551 numchars--;
7552 count++;
7554 break;
7556 case WM_SYSCHAR:
7557 case WM_CHAR:
7558 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7560 if (f && !f->iconified)
7562 if (temp_index == sizeof temp_buffer / sizeof (short))
7563 temp_index = 0;
7564 temp_buffer[temp_index++] = msg.msg.wParam;
7565 bufp->kind = ascii_keystroke;
7566 bufp->code = msg.msg.wParam;
7567 bufp->modifiers = msg.dwModifiers;
7568 XSETFRAME (bufp->frame_or_window, f);
7569 bufp->timestamp = msg.msg.time;
7570 bufp++;
7571 numchars--;
7572 count++;
7574 break;
7576 case WM_MOUSEMOVE:
7577 previous_help_echo = help_echo;
7578 help_echo = Qnil;
7580 if (dpyinfo->grabbed && last_mouse_frame
7581 && FRAME_LIVE_P (last_mouse_frame))
7582 f = last_mouse_frame;
7583 else
7584 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7586 if (f)
7587 note_mouse_movement (f, &msg.msg);
7588 else
7590 /* If we move outside the frame, then we're
7591 certainly no longer on any text in the frame. */
7592 clear_mouse_face (FRAME_W32_DISPLAY_INFO (f));
7595 /* If the contents of the global variable help_echo
7596 has changed, generate a HELP_EVENT. */
7597 if (STRINGP (help_echo)
7598 || STRINGP (previous_help_echo))
7600 Lisp_Object frame;
7602 if (f)
7603 XSETFRAME (frame, f);
7604 else
7605 frame = Qnil;
7607 any_help_event_p = 1;
7608 bufp->kind = HELP_EVENT;
7609 bufp->frame_or_window = Fcons (frame, help_echo);
7610 ++bufp, ++count, --numchars;
7612 break;
7614 case WM_LBUTTONDOWN:
7615 case WM_LBUTTONUP:
7616 case WM_MBUTTONDOWN:
7617 case WM_MBUTTONUP:
7618 case WM_RBUTTONDOWN:
7619 case WM_RBUTTONUP:
7621 /* If we decide we want to generate an event to be seen
7622 by the rest of Emacs, we put it here. */
7623 struct input_event emacs_event;
7624 int tool_bar_p = 0;
7625 int button;
7626 int up;
7628 emacs_event.kind = no_event;
7630 if (dpyinfo->grabbed && last_mouse_frame
7631 && FRAME_LIVE_P (last_mouse_frame))
7632 f = last_mouse_frame;
7633 else
7634 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7636 if (f)
7638 construct_mouse_click (&emacs_event, &msg, f);
7640 /* Is this in the tool-bar? */
7641 if (WINDOWP (f->tool_bar_window)
7642 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
7644 Lisp_Object window;
7645 int p, x, y;
7647 /* Set x and y. */
7648 window = window_from_coordinates (f,
7649 emacs_event.x,
7650 emacs_event.y,
7651 &p, 1);
7652 if (EQ (window, f->tool_bar_window))
7654 w32_handle_tool_bar_click (f, &emacs_event);
7655 tool_bar_p = 1;
7659 if (!tool_bar_p)
7660 if (!dpyinfo->w32_focus_frame
7661 || f == dpyinfo->w32_focus_frame
7662 && (numchars >= 1))
7664 construct_mouse_click (bufp, &msg, f);
7665 bufp++;
7666 count++;
7667 numchars--;
7671 parse_button (msg.msg.message, &button, &up);
7673 if (up)
7675 dpyinfo->grabbed &= ~ (1 << button);
7677 else
7679 dpyinfo->grabbed |= (1 << button);
7680 last_mouse_frame = f;
7681 /* Ignore any mouse motion that happened
7682 before this event; any subsequent mouse-movement
7683 Emacs events should reflect only motion after
7684 the ButtonPress. */
7685 if (f != 0)
7686 f->mouse_moved = 0;
7688 if (!tool_bar_p)
7689 last_tool_bar_item = -1;
7691 break;
7694 case WM_MOUSEWHEEL:
7695 if (dpyinfo->grabbed && last_mouse_frame
7696 && FRAME_LIVE_P (last_mouse_frame))
7697 f = last_mouse_frame;
7698 else
7699 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7701 if (f)
7703 if ((!dpyinfo->w32_focus_frame
7704 || f == dpyinfo->w32_focus_frame)
7705 && (numchars >= 1))
7707 construct_mouse_wheel (bufp, &msg, f);
7708 bufp++;
7709 count++;
7710 numchars--;
7713 break;
7715 case WM_MENUSELECT:
7717 HMENU menu = (HMENU) msg.msg.lParam;
7718 UINT menu_item = (UINT) LOWORD (msg.msg.wParam);
7719 UINT flags = (UINT) HIWORD (msg.msg.wParam);
7721 w32_menu_display_help (menu, menu_item, flags);
7723 break;
7725 case WM_DROPFILES:
7726 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7728 if (f)
7730 construct_drag_n_drop (bufp, &msg, f);
7731 bufp++;
7732 count++;
7733 numchars--;
7735 break;
7737 case WM_VSCROLL:
7739 struct scroll_bar *bar =
7740 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
7742 if (bar && numchars >= 1)
7744 if (x_scroll_bar_handle_click (bar, &msg, bufp))
7746 bufp++;
7747 count++;
7748 numchars--;
7751 break;
7754 case WM_WINDOWPOSCHANGED:
7755 case WM_ACTIVATE:
7756 case WM_ACTIVATEAPP:
7757 check_visibility = 1;
7758 break;
7760 case WM_MOVE:
7761 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7763 if (f && !f->async_iconified)
7765 int x, y;
7767 x_real_positions (f, &x, &y);
7768 f->output_data.w32->left_pos = x;
7769 f->output_data.w32->top_pos = y;
7772 check_visibility = 1;
7773 break;
7775 case WM_SHOWWINDOW:
7776 /* If window has been obscured or exposed by another window
7777 being maximised or minimised/restored, then recheck
7778 visibility of all frames. Direct changes to our own
7779 windows get handled by WM_SIZE. */
7780 #if 0
7781 if (msg.msg.lParam != 0)
7782 check_visibility = 1;
7783 else
7785 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7786 f->async_visible = msg.msg.wParam;
7788 #endif
7790 check_visibility = 1;
7791 break;
7793 case WM_SIZE:
7794 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7796 /* Inform lisp of whether frame has been iconified etc. */
7797 if (f)
7799 switch (msg.msg.wParam)
7801 case SIZE_MINIMIZED:
7802 f->async_visible = 0;
7803 f->async_iconified = 1;
7805 bufp->kind = iconify_event;
7806 XSETFRAME (bufp->frame_or_window, f);
7807 bufp++;
7808 count++;
7809 numchars--;
7810 break;
7812 case SIZE_MAXIMIZED:
7813 case SIZE_RESTORED:
7814 f->async_visible = 1;
7815 f->async_iconified = 0;
7817 /* wait_reading_process_input will notice this and update
7818 the frame's display structures. */
7819 SET_FRAME_GARBAGED (f);
7821 if (f->iconified)
7823 int x, y;
7825 /* Reset top and left positions of the Window
7826 here since Windows sends a WM_MOVE message
7827 BEFORE telling us the Window is minimized
7828 when the Window is iconified, with 3000,3000
7829 as the co-ords. */
7830 x_real_positions (f, &x, &y);
7831 f->output_data.w32->left_pos = x;
7832 f->output_data.w32->top_pos = y;
7834 bufp->kind = deiconify_event;
7835 XSETFRAME (bufp->frame_or_window, f);
7836 bufp++;
7837 count++;
7838 numchars--;
7840 else
7841 /* Force a redisplay sooner or later
7842 to update the frame titles
7843 in case this is the second frame. */
7844 record_asynch_buffer_change ();
7845 break;
7849 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
7851 RECT rect;
7852 int rows;
7853 int columns;
7854 int width;
7855 int height;
7857 GetClientRect(msg.msg.hwnd, &rect);
7859 height = rect.bottom - rect.top;
7860 width = rect.right - rect.left;
7862 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
7863 columns = PIXEL_TO_CHAR_WIDTH (f, width);
7865 /* TODO: Clip size to the screen dimensions. */
7867 /* Even if the number of character rows and columns has
7868 not changed, the font size may have changed, so we need
7869 to check the pixel dimensions as well. */
7871 if (columns != f->width
7872 || rows != f->height
7873 || width != f->output_data.w32->pixel_width
7874 || height != f->output_data.w32->pixel_height)
7876 change_frame_size (f, rows, columns, 0, 1, 0);
7877 SET_FRAME_GARBAGED (f);
7878 cancel_mouse_face (f);
7879 f->output_data.w32->pixel_width = width;
7880 f->output_data.w32->pixel_height = height;
7881 f->output_data.w32->win_gravity = NorthWestGravity;
7885 check_visibility = 1;
7886 break;
7888 case WM_SETFOCUS:
7889 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
7891 dpyinfo->w32_focus_event_frame = f;
7893 if (f)
7894 x_new_focus_frame (dpyinfo, f);
7897 dpyinfo->grabbed = 0;
7898 check_visibility = 1;
7899 break;
7901 case WM_KILLFOCUS:
7902 /* NTEMACS_TODO: some of this belongs in MOUSE_LEAVE */
7903 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
7905 if (f)
7907 Lisp_Object frame;
7909 if (f == dpyinfo->w32_focus_event_frame)
7910 dpyinfo->w32_focus_event_frame = 0;
7912 if (f == dpyinfo->w32_focus_frame)
7913 x_new_focus_frame (dpyinfo, 0);
7915 if (f == dpyinfo->mouse_face_mouse_frame)
7917 /* If we move outside the frame, then we're
7918 certainly no longer on any text in the frame. */
7919 clear_mouse_face (dpyinfo);
7920 dpyinfo->mouse_face_mouse_frame = 0;
7922 /* Generate a nil HELP_EVENT to cancel a help-echo.
7923 Do it only if there's something to cancel.
7924 Otherwise, the startup message is cleared when
7925 the mouse leaves the frame. */
7926 if (any_help_event_p)
7928 XSETFRAME (frame, f);
7929 bufp->kind = HELP_EVENT;
7930 bufp->frame_or_window = Fcons (frame, Qnil);
7931 ++bufp, ++count, --numchars;
7935 dpyinfo->grabbed = 0;
7936 check_visibility = 1;
7937 break;
7939 case WM_CLOSE:
7940 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7942 if (f)
7944 if (numchars == 0)
7945 abort ();
7947 bufp->kind = delete_window_event;
7948 XSETFRAME (bufp->frame_or_window, f);
7949 bufp++;
7950 count++;
7951 numchars--;
7953 break;
7955 case WM_INITMENU:
7956 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7958 if (f)
7960 if (numchars == 0)
7961 abort ();
7963 bufp->kind = menu_bar_activate_event;
7964 XSETFRAME (bufp->frame_or_window, f);
7965 bufp++;
7966 count++;
7967 numchars--;
7969 break;
7971 case WM_COMMAND:
7972 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7974 if (f)
7976 extern void menubar_selection_callback
7977 (FRAME_PTR f, void * client_data);
7978 menubar_selection_callback (f, (void *)msg.msg.wParam);
7981 check_visibility = 1;
7982 break;
7984 case WM_DISPLAYCHANGE:
7985 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
7987 if (f)
7989 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
7990 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
7991 dpyinfo->n_cbits = msg.msg.wParam;
7992 DebPrint (("display change: %d %d\n", dpyinfo->width,
7993 dpyinfo->height));
7996 check_visibility = 1;
7997 break;
7999 default:
8000 /* Check for messages registered at runtime. */
8001 if (msg.msg.message == msh_mousewheel)
8003 if (dpyinfo->grabbed && last_mouse_frame
8004 && FRAME_LIVE_P (last_mouse_frame))
8005 f = last_mouse_frame;
8006 else
8007 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8009 if (f)
8011 if ((!dpyinfo->w32_focus_frame
8012 || f == dpyinfo->w32_focus_frame)
8013 && (numchars >= 1))
8015 construct_mouse_wheel (bufp, &msg, f);
8016 bufp++;
8017 count++;
8018 numchars--;
8022 break;
8026 /* If the focus was just given to an autoraising frame,
8027 raise it now. */
8028 /* ??? This ought to be able to handle more than one such frame. */
8029 if (pending_autoraise_frame)
8031 x_raise_frame (pending_autoraise_frame);
8032 pending_autoraise_frame = 0;
8035 /* Check which frames are still visisble, if we have enqueued any user
8036 events or been notified of events that may affect visibility. We
8037 do this here because there doesn't seem to be any direct
8038 notification from Windows that the visibility of a window has
8039 changed (at least, not in all cases). */
8040 if (count > 0 || check_visibility)
8042 Lisp_Object tail, frame;
8044 FOR_EACH_FRAME (tail, frame)
8046 FRAME_PTR f = XFRAME (frame);
8047 /* Check "visible" frames and mark each as obscured or not.
8048 Note that async_visible is nonzero for unobscured and
8049 obscured frames, but zero for hidden and iconified frames. */
8050 if (FRAME_W32_P (f) && f->async_visible)
8052 RECT clipbox;
8053 HDC hdc = get_frame_dc (f);
8054 GetClipBox (hdc, &clipbox);
8055 release_frame_dc (f, hdc);
8057 if (clipbox.right == clipbox.left
8058 || clipbox.bottom == clipbox.top)
8060 /* Frame has become completely obscured so mark as
8061 such (we do this by setting async_visible to 2 so
8062 that FRAME_VISIBLE_P is still true, but redisplay
8063 will skip it). */
8064 f->async_visible = 2;
8066 if (!FRAME_OBSCURED_P (f))
8068 DebPrint (("frame %04x (%s) obscured\n", f,
8069 XSTRING (f->name)->data));
8072 else
8074 /* Frame is not obscured, so mark it as such. */
8075 f->async_visible = 1;
8077 if (FRAME_OBSCURED_P (f))
8079 SET_FRAME_GARBAGED (f);
8080 DebPrint (("frame %04x (%s) reexposed\n", f,
8081 XSTRING (f->name)->data));
8083 /* Force a redisplay sooner or later. */
8084 record_asynch_buffer_change ();
8091 UNBLOCK_INPUT;
8092 return count;
8096 /***********************************************************************
8097 Text Cursor
8098 ***********************************************************************/
8100 /* Note if the text cursor of window W has been overwritten by a
8101 drawing operation that outputs N glyphs starting at HPOS in the
8102 line given by output_cursor.vpos. N < 0 means all the rest of the
8103 line after HPOS has been written. */
8105 static void
8106 note_overwritten_text_cursor (w, hpos, n)
8107 struct window *w;
8108 int hpos, n;
8110 if (updated_area == TEXT_AREA
8111 && output_cursor.vpos == w->phys_cursor.vpos
8112 && hpos <= w->phys_cursor.hpos
8113 && (n < 0
8114 || hpos + n > w->phys_cursor.hpos))
8115 w->phys_cursor_on_p = 0;
8119 /* Set clipping for output in glyph row ROW. W is the window in which
8120 we operate. GC is the graphics context to set clipping in.
8121 WHOLE_LINE_P non-zero means include the areas used for truncation
8122 mark display and alike in the clipping rectangle.
8124 ROW may be a text row or, e.g., a mode line. Text rows must be
8125 clipped to the interior of the window dedicated to text display,
8126 mode lines must be clipped to the whole window. */
8128 static void
8129 w32_clip_to_row (w, row, hdc, whole_line_p)
8130 struct window *w;
8131 struct glyph_row *row;
8132 HDC hdc;
8133 int whole_line_p;
8135 struct frame *f = XFRAME (WINDOW_FRAME (w));
8136 RECT clip_rect;
8137 int window_x, window_y, window_width, window_height;
8139 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
8141 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
8142 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
8143 clip_rect.top = max (clip_rect.top, window_y);
8144 clip_rect.right = clip_rect.left + window_width;
8145 clip_rect.bottom = clip_rect.top + row->visible_height;
8147 /* If clipping to the whole line, including trunc marks, extend
8148 the rectangle to the left and right. */
8149 if (whole_line_p)
8151 clip_rect.left -= FRAME_X_LEFT_FLAGS_AREA_WIDTH (f);
8152 clip_rect.right += FRAME_X_FLAGS_AREA_WIDTH (f);
8155 w32_set_clip_rectangle (hdc, &clip_rect);
8159 /* Draw a hollow box cursor on window W in glyph row ROW. */
8161 static void
8162 x_draw_hollow_cursor (w, row)
8163 struct window *w;
8164 struct glyph_row *row;
8166 struct frame *f = XFRAME (WINDOW_FRAME (w));
8167 HDC hdc = get_frame_dc (f);
8168 RECT rect;
8169 int wd;
8170 struct glyph *cursor_glyph;
8171 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
8173 /* Compute frame-relative coordinates from window-relative
8174 coordinates. */
8175 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8176 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
8177 + row->ascent - w->phys_cursor_ascent);
8178 rect.bottom = rect.top + row->height - 1;
8180 /* Get the glyph the cursor is on. If we can't tell because
8181 the current matrix is invalid or such, give up. */
8182 cursor_glyph = get_phys_cursor_glyph (w);
8183 if (cursor_glyph == NULL)
8184 return;
8186 /* Compute the width of the rectangle to draw. If on a stretch
8187 glyph, and `x-stretch-block-cursor' is nil, don't draw a
8188 rectangle as wide as the glyph, but use a canonical character
8189 width instead. */
8190 wd = cursor_glyph->pixel_width - 1;
8191 if (cursor_glyph->type == STRETCH_GLYPH
8192 && !x_stretch_cursor_p)
8193 wd = min (CANON_X_UNIT (f), wd);
8195 rect.right = rect.left + wd;
8197 FrameRect (hdc, &rect, hb);
8198 DeleteObject (hb);
8200 release_frame_dc (f, hdc);
8204 /* Draw a bar cursor on window W in glyph row ROW.
8206 Implementation note: One would like to draw a bar cursor with an
8207 angle equal to the one given by the font property XA_ITALIC_ANGLE.
8208 Unfortunately, I didn't find a font yet that has this property set.
8209 --gerd. */
8211 static void
8212 x_draw_bar_cursor (w, row)
8213 struct window *w;
8214 struct glyph_row *row;
8216 /* If cursor hpos is out of bounds, don't draw garbage. This can
8217 happen in mini-buffer windows when switching between echo area
8218 glyphs and mini-buffer. */
8219 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8221 struct frame *f = XFRAME (w->frame);
8222 struct glyph *cursor_glyph;
8223 int x;
8224 HDC hdc;
8226 cursor_glyph = get_phys_cursor_glyph (w);
8227 if (cursor_glyph == NULL)
8228 return;
8230 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8232 hdc = get_frame_dc (f);
8233 w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
8235 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
8236 min (cursor_glyph->pixel_width,
8237 f->output_data.w32->cursor_width),
8238 row->height);
8239 release_frame_dc (f, hdc);
8244 /* Clear the cursor of window W to background color, and mark the
8245 cursor as not shown. This is used when the text where the cursor
8246 is is about to be rewritten. */
8248 static void
8249 x_clear_cursor (w)
8250 struct window *w;
8252 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
8253 x_update_window_cursor (w, 0);
8257 /* Draw the cursor glyph of window W in glyph row ROW. See the
8258 comment of x_draw_glyphs for the meaning of HL. */
8260 static void
8261 x_draw_phys_cursor_glyph (w, row, hl)
8262 struct window *w;
8263 struct glyph_row *row;
8264 enum draw_glyphs_face hl;
8266 /* If cursor hpos is out of bounds, don't draw garbage. This can
8267 happen in mini-buffer windows when switching between echo area
8268 glyphs and mini-buffer. */
8269 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
8271 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
8272 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
8273 hl, 0, 0, 0);
8275 /* When we erase the cursor, and ROW is overlapped by other
8276 rows, make sure that these overlapping parts of other rows
8277 are redrawn. */
8278 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
8280 if (row > w->current_matrix->rows
8281 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
8282 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
8284 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
8285 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
8286 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
8292 /* Erase the image of a cursor of window W from the screen. */
8294 static void
8295 x_erase_phys_cursor (w)
8296 struct window *w;
8298 struct frame *f = XFRAME (w->frame);
8299 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8300 int hpos = w->phys_cursor.hpos;
8301 int vpos = w->phys_cursor.vpos;
8302 int mouse_face_here_p = 0;
8303 struct glyph_matrix *active_glyphs = w->current_matrix;
8304 struct glyph_row *cursor_row;
8305 struct glyph *cursor_glyph;
8306 enum draw_glyphs_face hl;
8308 /* No cursor displayed or row invalidated => nothing to do on the
8309 screen. */
8310 if (w->phys_cursor_type == NO_CURSOR)
8311 goto mark_cursor_off;
8313 /* VPOS >= active_glyphs->nrows means that window has been resized.
8314 Don't bother to erase the cursor. */
8315 if (vpos >= active_glyphs->nrows)
8316 goto mark_cursor_off;
8318 /* If row containing cursor is marked invalid, there is nothing we
8319 can do. */
8320 cursor_row = MATRIX_ROW (active_glyphs, vpos);
8321 if (!cursor_row->enabled_p)
8322 goto mark_cursor_off;
8324 /* This can happen when the new row is shorter than the old one.
8325 In this case, either x_draw_glyphs or clear_end_of_line
8326 should have cleared the cursor. Note that we wouldn't be
8327 able to erase the cursor in this case because we don't have a
8328 cursor glyph at hand. */
8329 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
8330 goto mark_cursor_off;
8332 /* If the cursor is in the mouse face area, redisplay that when
8333 we clear the cursor. */
8334 if (w == XWINDOW (dpyinfo->mouse_face_window)
8335 && (vpos > dpyinfo->mouse_face_beg_row
8336 || (vpos == dpyinfo->mouse_face_beg_row
8337 && hpos >= dpyinfo->mouse_face_beg_col))
8338 && (vpos < dpyinfo->mouse_face_end_row
8339 || (vpos == dpyinfo->mouse_face_end_row
8340 && hpos < dpyinfo->mouse_face_end_col))
8341 /* Don't redraw the cursor's spot in mouse face if it is at the
8342 end of a line (on a newline). The cursor appears there, but
8343 mouse highlighting does not. */
8344 && cursor_row->used[TEXT_AREA] > hpos)
8345 mouse_face_here_p = 1;
8347 /* Maybe clear the display under the cursor. */
8348 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
8350 int x;
8351 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
8352 HDC hdc;
8354 cursor_glyph = get_phys_cursor_glyph (w);
8355 if (cursor_glyph == NULL)
8356 goto mark_cursor_off;
8358 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8360 hdc = get_frame_dc (f);
8361 w32_clear_area (f, hdc, x,
8362 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
8363 cursor_row->y)),
8364 cursor_glyph->pixel_width,
8365 cursor_row->visible_height);
8366 release_frame_dc (f, hdc);
8369 /* Erase the cursor by redrawing the character underneath it. */
8370 if (mouse_face_here_p)
8371 hl = DRAW_MOUSE_FACE;
8372 else if (cursor_row->inverse_p)
8373 hl = DRAW_INVERSE_VIDEO;
8374 else
8375 hl = DRAW_NORMAL_TEXT;
8376 x_draw_phys_cursor_glyph (w, cursor_row, hl);
8378 mark_cursor_off:
8379 w->phys_cursor_on_p = 0;
8380 w->phys_cursor_type = NO_CURSOR;
8384 /* Display or clear cursor of window W. If ON is zero, clear the
8385 cursor. If it is non-zero, display the cursor. If ON is nonzero,
8386 where to put the cursor is specified by HPOS, VPOS, X and Y. */
8388 void
8389 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
8390 struct window *w;
8391 int on, hpos, vpos, x, y;
8393 struct frame *f = XFRAME (w->frame);
8394 int new_cursor_type;
8395 struct glyph_matrix *current_glyphs;
8396 struct glyph_row *glyph_row;
8397 struct glyph *glyph;
8399 /* This is pointless on invisible frames, and dangerous on garbaged
8400 windows and frames; in the latter case, the frame or window may
8401 be in the midst of changing its size, and x and y may be off the
8402 window. */
8403 if (! FRAME_VISIBLE_P (f)
8404 || FRAME_GARBAGED_P (f)
8405 || vpos >= w->current_matrix->nrows
8406 || hpos >= w->current_matrix->matrix_w)
8407 return;
8409 /* If cursor is off and we want it off, return quickly. */
8410 if (!on && !w->phys_cursor_on_p)
8411 return;
8413 current_glyphs = w->current_matrix;
8414 glyph_row = MATRIX_ROW (current_glyphs, vpos);
8415 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
8417 /* If cursor row is not enabled, we don't really know where to
8418 display the cursor. */
8419 if (!glyph_row->enabled_p)
8421 w->phys_cursor_on_p = 0;
8422 return;
8425 xassert (interrupt_input_blocked);
8427 /* Set new_cursor_type to the cursor we want to be displayed. In a
8428 mini-buffer window, we want the cursor only to appear if we are
8429 reading input from this window. For the selected window, we want
8430 the cursor type given by the frame parameter. If explicitly
8431 marked off, draw no cursor. In all other cases, we want a hollow
8432 box cursor. */
8433 if (cursor_in_echo_area
8434 && FRAME_HAS_MINIBUF_P (f)
8435 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
8437 if (w == XWINDOW (echo_area_window))
8438 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8439 else
8440 new_cursor_type = HOLLOW_BOX_CURSOR;
8442 else
8444 if (w != XWINDOW (selected_window)
8445 || f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame)
8447 extern int cursor_in_non_selected_windows;
8449 if (MINI_WINDOW_P (w) || !cursor_in_non_selected_windows)
8450 new_cursor_type = NO_CURSOR;
8451 else
8452 new_cursor_type = HOLLOW_BOX_CURSOR;
8454 else if (w->cursor_off_p)
8455 new_cursor_type = NO_CURSOR;
8456 else
8457 new_cursor_type = FRAME_DESIRED_CURSOR (f);
8460 /* If cursor is currently being shown and we don't want it to be or
8461 it is in the wrong place, or the cursor type is not what we want,
8462 erase it. */
8463 if (w->phys_cursor_on_p
8464 && (!on
8465 || w->phys_cursor.x != x
8466 || w->phys_cursor.y != y
8467 || new_cursor_type != w->phys_cursor_type))
8468 x_erase_phys_cursor (w);
8470 /* If the cursor is now invisible and we want it to be visible,
8471 display it. */
8472 if (on && !w->phys_cursor_on_p)
8474 w->phys_cursor_ascent = glyph_row->ascent;
8475 w->phys_cursor_height = glyph_row->height;
8477 /* Set phys_cursor_.* before x_draw_.* is called because some
8478 of them may need the information. */
8479 w->phys_cursor.x = x;
8480 w->phys_cursor.y = glyph_row->y;
8481 w->phys_cursor.hpos = hpos;
8482 w->phys_cursor.vpos = vpos;
8483 w->phys_cursor_type = new_cursor_type;
8484 w->phys_cursor_on_p = 1;
8486 switch (new_cursor_type)
8488 case HOLLOW_BOX_CURSOR:
8489 x_draw_hollow_cursor (w, glyph_row);
8490 break;
8492 case FILLED_BOX_CURSOR:
8493 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
8494 break;
8496 case BAR_CURSOR:
8497 x_draw_bar_cursor (w, glyph_row);
8498 break;
8500 case NO_CURSOR:
8501 break;
8503 default:
8504 abort ();
8510 /* Display the cursor on window W, or clear it. X and Y are window
8511 relative pixel coordinates. HPOS and VPOS are glyph matrix
8512 positions. If W is not the selected window, display a hollow
8513 cursor. ON non-zero means display the cursor at X, Y which
8514 correspond to HPOS, VPOS, otherwise it is cleared. */
8516 void
8517 x_display_cursor (w, on, hpos, vpos, x, y)
8518 struct window *w;
8519 int on, hpos, vpos, x, y;
8521 BLOCK_INPUT;
8522 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
8523 UNBLOCK_INPUT;
8527 /* Display the cursor on window W, or clear it, according to ON_P.
8528 Don't change the cursor's position. */
8530 void
8531 x_update_cursor (f, on_p)
8532 struct frame *f;
8533 int on_p;
8535 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
8539 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
8540 in the window tree rooted at W. */
8542 static void
8543 x_update_cursor_in_window_tree (w, on_p)
8544 struct window *w;
8545 int on_p;
8547 while (w)
8549 if (!NILP (w->hchild))
8550 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
8551 else if (!NILP (w->vchild))
8552 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
8553 else
8554 x_update_window_cursor (w, on_p);
8556 w = NILP (w->next) ? 0 : XWINDOW (w->next);
8561 /* Switch the display of W's cursor on or off, according to the value
8562 of ON. */
8564 static void
8565 x_update_window_cursor (w, on)
8566 struct window *w;
8567 int on;
8569 BLOCK_INPUT;
8570 x_display_and_set_cursor (w, on, w->phys_cursor.hpos, w->phys_cursor.vpos,
8571 w->phys_cursor.x, w->phys_cursor.y);
8572 UNBLOCK_INPUT;
8577 /* Icons. */
8580 x_bitmap_icon (f, icon)
8581 struct frame *f;
8582 Lisp_Object icon;
8584 int mask, bitmap_id;
8585 Window icon_window;
8586 HANDLE hicon;
8588 if (FRAME_W32_WINDOW (f) == 0)
8589 return 1;
8591 if (NILP (icon))
8592 hicon = LoadIcon (hinst, EMACS_CLASS);
8593 else if (STRINGP (icon))
8594 hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
8595 LR_DEFAULTSIZE | LR_LOADFROMFILE);
8596 else if (SYMBOLP (icon))
8598 LPCTSTR name;
8600 if (EQ (icon, intern ("application")))
8601 name = (LPCTSTR) IDI_APPLICATION;
8602 else if (EQ (icon, intern ("hand")))
8603 name = (LPCTSTR) IDI_HAND;
8604 else if (EQ (icon, intern ("question")))
8605 name = (LPCTSTR) IDI_QUESTION;
8606 else if (EQ (icon, intern ("exclamation")))
8607 name = (LPCTSTR) IDI_EXCLAMATION;
8608 else if (EQ (icon, intern ("asterisk")))
8609 name = (LPCTSTR) IDI_ASTERISK;
8610 else if (EQ (icon, intern ("winlogo")))
8611 name = (LPCTSTR) IDI_WINLOGO;
8612 else
8613 return 1;
8615 hicon = LoadIcon (NULL, name);
8617 else
8618 return 1;
8620 if (hicon == NULL)
8621 return 1;
8623 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
8624 (LPARAM) hicon);
8626 return 0;
8630 /* Changing the font of the frame. */
8632 /* Give frame F the font named FONTNAME as its default font, and
8633 return the full name of that font. FONTNAME may be a wildcard
8634 pattern; in that case, we choose some font that fits the pattern.
8635 The return value shows which font we chose. */
8637 Lisp_Object
8638 x_new_font (f, fontname)
8639 struct frame *f;
8640 register char *fontname;
8642 struct font_info *fontp
8643 = FS_LOAD_FONT (f, 0, fontname, -1);
8645 if (!fontp)
8646 return Qnil;
8648 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
8649 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
8650 FRAME_FONTSET (f) = -1;
8652 /* Compute the scroll bar width in character columns. */
8653 if (f->scroll_bar_pixel_width > 0)
8655 int wid = FONT_WIDTH (f->output_data.w32->font);
8656 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
8658 else
8659 f->scroll_bar_cols = 2;
8661 /* Now make the frame display the given font. */
8662 if (FRAME_W32_WINDOW (f) != 0)
8664 frame_update_line_height (f);
8665 x_set_window_size (f, 0, f->width, f->height);
8667 else
8668 /* If we are setting a new frame's font for the first time,
8669 there are no faces yet, so this font's height is the line height. */
8670 f->output_data.w32->line_height = FONT_HEIGHT (f->output_data.w32->font);
8672 return build_string (fontp->full_name);
8675 /* Give frame F the fontset named FONTSETNAME as its default font, and
8676 return the full name of that fontset. FONTSETNAME may be a wildcard
8677 pattern; in that case, we choose some fontset that fits the pattern.
8678 The return value shows which fontset we chose. */
8680 Lisp_Object
8681 x_new_fontset (f, fontsetname)
8682 struct frame *f;
8683 char *fontsetname;
8685 int fontset = fs_query_fontset (build_string (fontsetname), 0);
8686 Lisp_Object result;
8687 char *fontname;
8689 if (fontset < 0)
8690 return Qnil;
8692 if (FRAME_FONTSET (f) == fontset)
8693 /* This fontset is already set in frame F. There's nothing more
8694 to do. */
8695 return fontset_name (fontset);
8697 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
8699 if (!STRINGP (result))
8700 /* Can't load ASCII font. */
8701 return Qnil;
8703 /* Since x_new_font doesn't update any fontset information, do it now. */
8704 FRAME_FONTSET(f) = fontset;
8706 return build_string (fontsetname);
8710 #if GLYPH_DEBUG
8712 /* Check that FONT is valid on frame F. It is if it can be found in F's
8713 font table. */
8715 static void
8716 x_check_font (f, font)
8717 struct frame *f;
8718 XFontStruct *font;
8720 int i;
8721 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8723 xassert (font != NULL);
8725 for (i = 0; i < dpyinfo->n_fonts; i++)
8726 if (dpyinfo->font_table[i].name
8727 && font == dpyinfo->font_table[i].font)
8728 break;
8730 xassert (i < dpyinfo->n_fonts);
8733 #endif /* GLYPH_DEBUG != 0 */
8735 /* Set *W to the minimum width, *H to the minimum font height of FONT.
8736 Note: There are (broken) X fonts out there with invalid XFontStruct
8737 min_bounds contents. For example, handa@etl.go.jp reports that
8738 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
8739 have font->min_bounds.width == 0. */
8741 static INLINE void
8742 x_font_min_bounds (font, w, h)
8743 XFontStruct *font;
8744 int *w, *h;
8746 *h = FONT_HEIGHT (font);
8747 *w = FONT_WIDTH (font);
8748 #if 0 /* NTEMACS_TODO: min/max bounds of Windows fonts */
8749 *w = font->min_bounds.width;
8751 /* Try to handle the case where FONT->min_bounds has invalid
8752 contents. Since the only font known to have invalid min_bounds
8753 is fixed-width, use max_bounds if min_bounds seems to be invalid. */
8754 if (*w <= 0)
8755 *w = font->max_bounds.width;
8756 #endif
8760 /* Compute the smallest character width and smallest font height over
8761 all fonts available on frame F. Set the members smallest_char_width
8762 and smallest_font_height in F's x_display_info structure to
8763 the values computed. Value is non-zero if smallest_font_height or
8764 smallest_char_width become smaller than they were before. */
8767 x_compute_min_glyph_bounds (f)
8768 struct frame *f;
8770 int i;
8771 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
8772 XFontStruct *font;
8773 int old_width = dpyinfo->smallest_char_width;
8774 int old_height = dpyinfo->smallest_font_height;
8776 dpyinfo->smallest_font_height = 100000;
8777 dpyinfo->smallest_char_width = 100000;
8779 for (i = 0; i < dpyinfo->n_fonts; ++i)
8780 if (dpyinfo->font_table[i].name)
8782 struct font_info *fontp = dpyinfo->font_table + i;
8783 int w, h;
8785 font = (XFontStruct *) fontp->font;
8786 xassert (font != (XFontStruct *) ~0);
8787 x_font_min_bounds (font, &w, &h);
8789 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
8790 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
8793 xassert (dpyinfo->smallest_char_width > 0
8794 && dpyinfo->smallest_font_height > 0);
8796 return (dpyinfo->n_fonts == 1
8797 || dpyinfo->smallest_char_width < old_width
8798 || dpyinfo->smallest_font_height < old_height);
8802 /* Calculate the absolute position in frame F
8803 from its current recorded position values and gravity. */
8805 x_calc_absolute_position (f)
8806 struct frame *f;
8808 Window child;
8809 POINT pt;
8810 int flags = f->output_data.w32->size_hint_flags;
8812 pt.x = pt.y = 0;
8814 /* Find the position of the outside upper-left corner of
8815 the inner window, with respect to the outer window. */
8816 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
8818 BLOCK_INPUT;
8819 MapWindowPoints (FRAME_W32_WINDOW (f),
8820 f->output_data.w32->parent_desc,
8821 &pt, 1);
8822 UNBLOCK_INPUT;
8826 RECT rt;
8827 rt.left = rt.right = rt.top = rt.bottom = 0;
8829 BLOCK_INPUT;
8830 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
8831 FRAME_EXTERNAL_MENU_BAR (f));
8832 UNBLOCK_INPUT;
8834 pt.x += (rt.right - rt.left);
8835 pt.y += (rt.bottom - rt.top);
8838 /* Treat negative positions as relative to the leftmost bottommost
8839 position that fits on the screen. */
8840 if (flags & XNegative)
8841 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
8842 - 2 * f->output_data.w32->border_width - pt.x
8843 - PIXEL_WIDTH (f)
8844 + f->output_data.w32->left_pos);
8845 /* NTEMACS_TODO: Subtract menubar height? */
8846 if (flags & YNegative)
8847 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
8848 - 2 * f->output_data.w32->border_width - pt.y
8849 - PIXEL_HEIGHT (f)
8850 + f->output_data.w32->top_pos);
8851 /* The left_pos and top_pos
8852 are now relative to the top and left screen edges,
8853 so the flags should correspond. */
8854 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
8857 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
8858 to really change the position, and 0 when calling from
8859 x_make_frame_visible (in that case, XOFF and YOFF are the current
8860 position values). It is -1 when calling from x_set_frame_parameters,
8861 which means, do adjust for borders but don't change the gravity. */
8863 x_set_offset (f, xoff, yoff, change_gravity)
8864 struct frame *f;
8865 register int xoff, yoff;
8866 int change_gravity;
8868 int modified_top, modified_left;
8870 if (change_gravity > 0)
8872 f->output_data.w32->top_pos = yoff;
8873 f->output_data.w32->left_pos = xoff;
8874 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
8875 if (xoff < 0)
8876 f->output_data.w32->size_hint_flags |= XNegative;
8877 if (yoff < 0)
8878 f->output_data.w32->size_hint_flags |= YNegative;
8879 f->output_data.w32->win_gravity = NorthWestGravity;
8881 x_calc_absolute_position (f);
8883 BLOCK_INPUT;
8884 x_wm_set_size_hint (f, (long) 0, 0);
8886 /* It is a mystery why we need to add the border_width here
8887 when the frame is already visible, but experiment says we do. */
8888 modified_left = f->output_data.w32->left_pos;
8889 modified_top = f->output_data.w32->top_pos;
8890 #ifndef HAVE_NTGUI
8891 /* Do not add in border widths under W32. */
8892 if (change_gravity != 0)
8894 modified_left += f->output_data.w32->border_width;
8895 modified_top += f->output_data.w32->border_width;
8897 #endif
8899 my_set_window_pos (FRAME_W32_WINDOW (f),
8900 NULL,
8901 modified_left, modified_top,
8902 0, 0,
8903 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
8904 UNBLOCK_INPUT;
8907 /* Call this to change the size of frame F's x-window.
8908 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
8909 for this size change and subsequent size changes.
8910 Otherwise we leave the window gravity unchanged. */
8911 void
8912 x_set_window_size (f, change_gravity, cols, rows)
8913 struct frame *f;
8914 int change_gravity;
8915 int cols, rows;
8917 int pixelwidth, pixelheight;
8919 BLOCK_INPUT;
8921 check_frame_size (f, &rows, &cols);
8922 f->output_data.w32->vertical_scroll_bar_extra
8923 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
8925 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
8926 f->output_data.w32->flags_areas_extra
8927 = FRAME_FLAGS_AREA_WIDTH (f);
8928 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
8929 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
8931 f->output_data.w32->win_gravity = NorthWestGravity;
8932 x_wm_set_size_hint (f, (long) 0, 0);
8935 RECT rect;
8937 rect.left = rect.top = 0;
8938 rect.right = pixelwidth;
8939 rect.bottom = pixelheight;
8941 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
8942 FRAME_EXTERNAL_MENU_BAR (f));
8944 my_set_window_pos (FRAME_W32_WINDOW (f),
8945 NULL,
8946 0, 0,
8947 rect.right - rect.left,
8948 rect.bottom - rect.top,
8949 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
8952 /* Now, strictly speaking, we can't be sure that this is accurate,
8953 but the window manager will get around to dealing with the size
8954 change request eventually, and we'll hear how it went when the
8955 ConfigureNotify event gets here.
8957 We could just not bother storing any of this information here,
8958 and let the ConfigureNotify event set everything up, but that
8959 might be kind of confusing to the lisp code, since size changes
8960 wouldn't be reported in the frame parameters until some random
8961 point in the future when the ConfigureNotify event arrives.
8963 We pass 1 for DELAY since we can't run Lisp code inside of
8964 a BLOCK_INPUT. */
8965 change_frame_size (f, rows, cols, 0, 1, 0);
8966 PIXEL_WIDTH (f) = pixelwidth;
8967 PIXEL_HEIGHT (f) = pixelheight;
8969 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
8970 receive in the ConfigureNotify event; if we get what we asked
8971 for, then the event won't cause the screen to become garbaged, so
8972 we have to make sure to do it here. */
8973 SET_FRAME_GARBAGED (f);
8975 /* If cursor was outside the new size, mark it as off. */
8976 mark_window_cursors_off (XWINDOW (f->root_window));
8978 /* Clear out any recollection of where the mouse highlighting was,
8979 since it might be in a place that's outside the new frame size.
8980 Actually checking whether it is outside is a pain in the neck,
8981 so don't try--just let the highlighting be done afresh with new size. */
8982 cancel_mouse_face (f);
8984 UNBLOCK_INPUT;
8987 /* Mouse warping. */
8989 void
8990 x_set_mouse_pixel_position (f, pix_x, pix_y)
8991 struct frame *f;
8992 int pix_x, pix_y;
8994 RECT rect;
8995 POINT pt;
8997 BLOCK_INPUT;
8999 GetClientRect (FRAME_W32_WINDOW (f), &rect);
9000 pt.x = rect.left + pix_x;
9001 pt.y = rect.top + pix_y;
9002 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
9004 SetCursorPos (pt.x, pt.y);
9006 UNBLOCK_INPUT;
9009 void
9010 x_set_mouse_position (f, x, y)
9011 struct frame *f;
9012 int x, y;
9014 int pix_x, pix_y;
9016 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
9017 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
9019 if (pix_x < 0) pix_x = 0;
9020 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
9022 if (pix_y < 0) pix_y = 0;
9023 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
9025 x_set_mouse_pixel_position (f, pix_x, pix_y);
9028 /* focus shifting, raising and lowering. */
9030 x_focus_on_frame (f)
9031 struct frame *f;
9033 struct w32_display_info *dpyinfo = &one_w32_display_info;
9035 /* Give input focus to frame. */
9036 BLOCK_INPUT;
9037 #if 0
9038 /* Try not to change its Z-order if possible. */
9039 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
9040 my_set_focus (f, FRAME_W32_WINDOW (f));
9041 else
9042 #endif
9043 my_set_foreground_window (FRAME_W32_WINDOW (f));
9044 UNBLOCK_INPUT;
9047 x_unfocus_frame (f)
9048 struct frame *f;
9052 /* Raise frame F. */
9053 void
9054 x_raise_frame (f)
9055 struct frame *f;
9057 BLOCK_INPUT;
9059 /* Strictly speaking, raise-frame should only change the frame's Z
9060 order, leaving input focus unchanged. This is reasonable behaviour
9061 on X where the usual policy is point-to-focus. However, this
9062 behaviour would be very odd on Windows where the usual policy is
9063 click-to-focus.
9065 On X, if the mouse happens to be over the raised frame, it gets
9066 input focus anyway (so the window with focus will never be
9067 completely obscured) - if not, then just moving the mouse over it
9068 is sufficient to give it focus. On Windows, the user must actually
9069 click on the frame (preferrably the title bar so as not to move
9070 point), which is more awkward. Also, no other Windows program
9071 raises a window to the top but leaves another window (possibly now
9072 completely obscured) with input focus.
9074 Because there is a system setting on Windows that allows the user
9075 to choose the point to focus policy, we make the strict semantics
9076 optional, but by default we grab focus when raising. */
9078 if (NILP (Vw32_grab_focus_on_raise))
9080 /* The obvious call to my_set_window_pos doesn't work if Emacs is
9081 not already the foreground application: the frame is raised
9082 above all other frames belonging to us, but not above the
9083 current top window. To achieve that, we have to resort to this
9084 more cumbersome method. */
9086 HDWP handle = BeginDeferWindowPos (2);
9087 if (handle)
9089 DeferWindowPos (handle,
9090 FRAME_W32_WINDOW (f),
9091 HWND_TOP,
9092 0, 0, 0, 0,
9093 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9095 DeferWindowPos (handle,
9096 GetForegroundWindow (),
9097 FRAME_W32_WINDOW (f),
9098 0, 0, 0, 0,
9099 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9101 EndDeferWindowPos (handle);
9104 else
9106 my_set_foreground_window (FRAME_W32_WINDOW (f));
9109 UNBLOCK_INPUT;
9112 /* Lower frame F. */
9113 void
9114 x_lower_frame (f)
9115 struct frame *f;
9117 BLOCK_INPUT;
9118 my_set_window_pos (FRAME_W32_WINDOW (f),
9119 HWND_BOTTOM,
9120 0, 0, 0, 0,
9121 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
9122 UNBLOCK_INPUT;
9125 static void
9126 w32_frame_raise_lower (f, raise)
9127 FRAME_PTR f;
9128 int raise;
9130 if (raise)
9131 x_raise_frame (f);
9132 else
9133 x_lower_frame (f);
9136 /* Change of visibility. */
9138 /* This tries to wait until the frame is really visible.
9139 However, if the window manager asks the user where to position
9140 the frame, this will return before the user finishes doing that.
9141 The frame will not actually be visible at that time,
9142 but it will become visible later when the window manager
9143 finishes with it. */
9145 x_make_frame_visible (f)
9146 struct frame *f;
9148 Lisp_Object type;
9150 BLOCK_INPUT;
9152 type = x_icon_type (f);
9153 if (!NILP (type))
9154 x_bitmap_icon (f, type);
9156 if (! FRAME_VISIBLE_P (f))
9158 /* We test FRAME_GARBAGED_P here to make sure we don't
9159 call x_set_offset a second time
9160 if we get to x_make_frame_visible a second time
9161 before the window gets really visible. */
9162 if (! FRAME_ICONIFIED_P (f)
9163 && ! f->output_data.w32->asked_for_visible)
9164 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
9166 f->output_data.w32->asked_for_visible = 1;
9168 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
9169 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
9172 /* Synchronize to ensure Emacs knows the frame is visible
9173 before we do anything else. We do this loop with input not blocked
9174 so that incoming events are handled. */
9176 Lisp_Object frame;
9177 int count;
9179 /* This must come after we set COUNT. */
9180 UNBLOCK_INPUT;
9182 XSETFRAME (frame, f);
9184 /* Wait until the frame is visible. Process X events until a
9185 MapNotify event has been seen, or until we think we won't get a
9186 MapNotify at all.. */
9187 for (count = input_signal_count + 10;
9188 input_signal_count < count && !FRAME_VISIBLE_P (f);)
9190 /* Force processing of queued events. */
9191 /* NTEMACS_TODO: x_sync equivalent? */
9193 /* Machines that do polling rather than SIGIO have been observed
9194 to go into a busy-wait here. So we'll fake an alarm signal
9195 to let the handler know that there's something to be read.
9196 We used to raise a real alarm, but it seems that the handler
9197 isn't always enabled here. This is probably a bug. */
9198 if (input_polling_used ())
9200 /* It could be confusing if a real alarm arrives while processing
9201 the fake one. Turn it off and let the handler reset it. */
9202 int old_poll_suppress_count = poll_suppress_count;
9203 poll_suppress_count = 1;
9204 poll_for_input_1 ();
9205 poll_suppress_count = old_poll_suppress_count;
9208 FRAME_SAMPLE_VISIBILITY (f);
9212 /* Change from mapped state to withdrawn state. */
9214 /* Make the frame visible (mapped and not iconified). */
9216 x_make_frame_invisible (f)
9217 struct frame *f;
9219 /* Don't keep the highlight on an invisible frame. */
9220 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
9221 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
9223 BLOCK_INPUT;
9225 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
9227 /* We can't distinguish this from iconification
9228 just by the event that we get from the server.
9229 So we can't win using the usual strategy of letting
9230 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
9231 and synchronize with the server to make sure we agree. */
9232 f->visible = 0;
9233 FRAME_ICONIFIED_P (f) = 0;
9234 f->async_visible = 0;
9235 f->async_iconified = 0;
9237 UNBLOCK_INPUT;
9240 /* Change window state from mapped to iconified. */
9242 void
9243 x_iconify_frame (f)
9244 struct frame *f;
9246 int result;
9247 Lisp_Object type;
9249 /* Don't keep the highlight on an invisible frame. */
9250 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
9251 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
9253 if (f->async_iconified)
9254 return;
9256 BLOCK_INPUT;
9258 type = x_icon_type (f);
9259 if (!NILP (type))
9260 x_bitmap_icon (f, type);
9262 /* Simulate the user minimizing the frame. */
9263 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
9265 UNBLOCK_INPUT;
9268 /* Destroy the window of frame F. */
9270 x_destroy_window (f)
9271 struct frame *f;
9273 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
9275 BLOCK_INPUT;
9277 my_destroy_window (f, FRAME_W32_WINDOW (f));
9278 free_frame_menubar (f);
9279 free_frame_faces (f);
9281 xfree (f->output_data.w32);
9282 f->output_data.w32 = 0;
9283 if (f == dpyinfo->w32_focus_frame)
9284 dpyinfo->w32_focus_frame = 0;
9285 if (f == dpyinfo->w32_focus_event_frame)
9286 dpyinfo->w32_focus_event_frame = 0;
9287 if (f == dpyinfo->w32_highlight_frame)
9288 dpyinfo->w32_highlight_frame = 0;
9290 dpyinfo->reference_count--;
9292 if (f == dpyinfo->mouse_face_mouse_frame)
9294 dpyinfo->mouse_face_beg_row
9295 = dpyinfo->mouse_face_beg_col = -1;
9296 dpyinfo->mouse_face_end_row
9297 = dpyinfo->mouse_face_end_col = -1;
9298 dpyinfo->mouse_face_window = Qnil;
9301 UNBLOCK_INPUT;
9304 /* Setting window manager hints. */
9306 /* Set the normal size hints for the window manager, for frame F.
9307 FLAGS is the flags word to use--or 0 meaning preserve the flags
9308 that the window now has.
9309 If USER_POSITION is nonzero, we set the USPosition
9310 flag (this is useful when FLAGS is 0). */
9311 void
9312 x_wm_set_size_hint (f, flags, user_position)
9313 struct frame *f;
9314 long flags;
9315 int user_position;
9317 Window window = FRAME_W32_WINDOW (f);
9319 enter_crit ();
9321 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
9322 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
9323 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
9324 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
9326 leave_crit ();
9329 /* Window manager things */
9330 x_wm_set_icon_position (f, icon_x, icon_y)
9331 struct frame *f;
9332 int icon_x, icon_y;
9334 #if 0
9335 Window window = FRAME_W32_WINDOW (f);
9337 f->display.x->wm_hints.flags |= IconPositionHint;
9338 f->display.x->wm_hints.icon_x = icon_x;
9339 f->display.x->wm_hints.icon_y = icon_y;
9341 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
9342 #endif
9346 /***********************************************************************
9347 Initialization
9348 ***********************************************************************/
9350 static int w32_initialized = 0;
9352 void
9353 w32_initialize_display_info (display_name)
9354 Lisp_Object display_name;
9356 struct w32_display_info *dpyinfo = &one_w32_display_info;
9358 bzero (dpyinfo, sizeof (*dpyinfo));
9360 /* Put it on w32_display_name_list. */
9361 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
9362 w32_display_name_list);
9363 dpyinfo->name_list_element = XCAR (w32_display_name_list);
9365 dpyinfo->w32_id_name
9366 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
9367 + XSTRING (Vsystem_name)->size
9368 + 2);
9369 sprintf (dpyinfo->w32_id_name, "%s@%s",
9370 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
9372 /* Default Console mode values - overridden when running in GUI mode
9373 with values obtained from system metrics. */
9374 dpyinfo->resx = 1;
9375 dpyinfo->resy = 1;
9376 dpyinfo->height_in = 1;
9377 dpyinfo->width_in = 1;
9378 dpyinfo->n_planes = 1;
9379 dpyinfo->n_cbits = 4;
9380 dpyinfo->n_fonts = 0;
9381 dpyinfo->smallest_font_height = 1;
9382 dpyinfo->smallest_char_width = 1;
9384 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9385 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9386 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9387 dpyinfo->mouse_face_window = Qnil;
9389 /* NTEMACS_TODO: dpyinfo->gray */
9393 struct w32_display_info *
9394 w32_term_init (display_name, xrm_option, resource_name)
9395 Lisp_Object display_name;
9396 char *xrm_option;
9397 char *resource_name;
9399 struct w32_display_info *dpyinfo;
9400 HDC hdc;
9402 BLOCK_INPUT;
9404 if (!w32_initialized)
9406 w32_initialize ();
9407 w32_initialized = 1;
9411 int argc = 0;
9412 char *argv[3];
9414 argv[0] = "";
9415 argc = 1;
9416 if (xrm_option)
9418 argv[argc++] = "-xrm";
9419 argv[argc++] = xrm_option;
9423 w32_initialize_display_info (display_name);
9425 dpyinfo = &one_w32_display_info;
9427 hdc = GetDC (GetDesktopWindow ());
9429 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
9430 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
9431 dpyinfo->root_window = GetDesktopWindow ();
9432 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
9433 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
9434 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
9435 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
9436 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
9437 dpyinfo->image_cache = make_image_cache ();
9438 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
9439 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
9440 ReleaseDC (GetDesktopWindow (), hdc);
9442 /* initialise palette with white and black */
9444 COLORREF color;
9445 w32_defined_color (0, "white", &color, 1);
9446 w32_defined_color (0, "black", &color, 1);
9449 /* Create Row Bitmaps and store them for later use. */
9450 left_bmp = CreateBitmap (left_width, left_height, 1, 1, left_bits);
9451 ov_bmp = CreateBitmap (ov_width, ov_height, 1, 1, ov_bits);
9452 right_bmp = CreateBitmap (right_width, right_height, 1, 1, right_bits);
9453 continued_bmp = CreateBitmap (continued_width, continued_height, 1,
9454 1, continued_bits);
9455 continuation_bmp = CreateBitmap (continuation_width, continuation_height,
9456 1, 1, continuation_bits);
9457 zv_bmp = CreateBitmap (zv_width, zv_height, 1, 1, zv_bits);
9459 #ifndef F_SETOWN_BUG
9460 #ifdef F_SETOWN
9461 #ifdef F_SETOWN_SOCK_NEG
9462 /* stdin is a socket here */
9463 fcntl (connection, F_SETOWN, -getpid ());
9464 #else /* ! defined (F_SETOWN_SOCK_NEG) */
9465 fcntl (connection, F_SETOWN, getpid ());
9466 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
9467 #endif /* ! defined (F_SETOWN) */
9468 #endif /* F_SETOWN_BUG */
9470 #ifdef SIGIO
9471 if (interrupt_input)
9472 init_sigio (connection);
9473 #endif /* ! defined (SIGIO) */
9475 UNBLOCK_INPUT;
9477 return dpyinfo;
9480 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9482 void
9483 x_delete_display (dpyinfo)
9484 struct w32_display_info *dpyinfo;
9486 /* Discard this display from w32_display_name_list and w32_display_list.
9487 We can't use Fdelq because that can quit. */
9488 if (! NILP (w32_display_name_list)
9489 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
9490 w32_display_name_list = XCDR (w32_display_name_list);
9491 else
9493 Lisp_Object tail;
9495 tail = w32_display_name_list;
9496 while (CONSP (tail) && CONSP (XCDR (tail)))
9498 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9500 XCDR (tail) = XCDR (XCDR (tail));
9501 break;
9503 tail = XCDR (tail);
9507 /* free palette table */
9509 struct w32_palette_entry * plist;
9511 plist = dpyinfo->color_list;
9512 while (plist)
9514 struct w32_palette_entry * pentry = plist;
9515 plist = plist->next;
9516 xfree(pentry);
9518 dpyinfo->color_list = NULL;
9519 if (dpyinfo->palette)
9520 DeleteObject(dpyinfo->palette);
9522 xfree (dpyinfo->font_table);
9523 xfree (dpyinfo->w32_id_name);
9525 /* Destroy row bitmaps. */
9526 DeleteObject (left_bmp);
9527 DeleteObject (ov_bmp);
9528 DeleteObject (right_bmp);
9529 DeleteObject (continued_bmp);
9530 DeleteObject (continuation_bmp);
9531 DeleteObject (zv_bmp);
9534 /* Set up use of W32. */
9536 DWORD w32_msg_worker ();
9538 void
9539 x_flush (struct frame * f)
9540 { /* Nothing to do */ }
9542 static struct redisplay_interface w32_redisplay_interface =
9544 x_produce_glyphs,
9545 x_write_glyphs,
9546 x_insert_glyphs,
9547 x_clear_end_of_line,
9548 x_scroll_run,
9549 x_after_update_window_line,
9550 x_update_window_begin,
9551 x_update_window_end,
9552 w32_cursor_to,
9553 x_flush,
9554 x_get_glyph_overhangs,
9555 x_fix_overlapping_area
9558 void
9559 w32_initialize ()
9561 rif = &w32_redisplay_interface;
9563 /* MSVC does not type K&R functions with no arguments correctly, and
9564 so we must explicitly cast them. */
9565 clear_frame_hook = (void (*)(void)) x_clear_frame;
9566 ins_del_lines_hook = x_ins_del_lines;
9567 change_line_highlight_hook = x_change_line_highlight;
9568 delete_glyphs_hook = x_delete_glyphs;
9569 ring_bell_hook = (void (*)(void)) w32_ring_bell;
9570 reset_terminal_modes_hook = (void (*)(void)) w32_reset_terminal_modes;
9571 set_terminal_modes_hook = (void (*)(void)) w32_set_terminal_modes;
9572 update_begin_hook = x_update_begin;
9573 update_end_hook = x_update_end;
9574 set_terminal_window_hook = w32_set_terminal_window;
9575 read_socket_hook = w32_read_socket;
9576 frame_up_to_date_hook = w32_frame_up_to_date;
9577 reassert_line_highlight_hook = w32_reassert_line_highlight;
9578 mouse_position_hook = w32_mouse_position;
9579 frame_rehighlight_hook = w32_frame_rehighlight;
9580 frame_raise_lower_hook = w32_frame_raise_lower;
9581 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
9582 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
9583 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
9584 judge_scroll_bars_hook = w32_judge_scroll_bars;
9585 estimate_mode_line_height_hook = x_estimate_mode_line_height;
9587 scroll_region_ok = 1; /* we'll scroll partial frames */
9588 char_ins_del_ok = 0; /* just as fast to write the line */
9589 line_ins_del_ok = 1; /* we'll just blt 'em */
9590 fast_clear_end_of_line = 1; /* X does this well */
9591 memory_below_frame = 0; /* we don't remember what scrolls
9592 off the bottom */
9593 baud_rate = 19200;
9595 last_tool_bar_item = -1;
9596 any_help_event_p = 0;
9598 /* Initialize input mode: interrupt_input off, no flow control, allow
9599 8 bit character input, standard quit char. */
9600 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
9602 /* Create the window thread - it will terminate itself or when the app terminates */
9604 init_crit ();
9606 dwMainThreadId = GetCurrentThreadId ();
9607 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
9608 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
9610 /* Wait for thread to start */
9613 MSG msg;
9615 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
9617 hWindowsThread = CreateThread (NULL, 0,
9618 (LPTHREAD_START_ROUTINE) w32_msg_worker,
9619 0, 0, &dwWindowsThreadId);
9621 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
9624 /* It is desirable that mainThread should have the same notion of
9625 focus window and active window as windowsThread. Unfortunately, the
9626 following call to AttachThreadInput, which should do precisely what
9627 we need, causes major problems when Emacs is linked as a console
9628 program. Unfortunately, we have good reasons for doing that, so
9629 instead we need to send messages to windowsThread to make some API
9630 calls for us (ones that affect, or depend on, the active/focus
9631 window state. */
9632 #ifdef ATTACH_THREADS
9633 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
9634 #endif
9636 /* Dynamically link to optional system components. */
9638 HANDLE user_lib = LoadLibrary ("user32.dll");
9640 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
9642 /* New proportional scroll bar functions. */
9643 LOAD_PROC( SetScrollInfo );
9644 LOAD_PROC( GetScrollInfo );
9646 #undef LOAD_PROC
9648 FreeLibrary (user_lib);
9650 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
9651 otherwise use the fixed height. */
9652 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
9653 GetSystemMetrics (SM_CYVTHUMB);
9655 /* For either kind of scroll bar, take account of the arrows; these
9656 effectively form the border of the main scroll bar range. */
9657 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
9658 = GetSystemMetrics (SM_CYVSCROLL);
9662 void
9663 syms_of_w32term ()
9665 Lisp_Object codepage;
9667 staticpro (&w32_display_name_list);
9668 w32_display_name_list = Qnil;
9670 staticpro (&last_mouse_scroll_bar);
9671 last_mouse_scroll_bar = Qnil;
9673 staticpro (&Qvendor_specific_keysyms);
9674 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9676 DEFVAR_INT ("w32-num-mouse-buttons",
9677 &Vw32_num_mouse_buttons,
9678 "Number of physical mouse buttons.");
9679 Vw32_num_mouse_buttons = Qnil;
9681 DEFVAR_LISP ("w32-swap-mouse-buttons",
9682 &Vw32_swap_mouse_buttons,
9683 "Swap the mapping of middle and right mouse buttons.\n\
9684 When nil, middle button is mouse-2 and right button is mouse-3.");
9685 Vw32_swap_mouse_buttons = Qnil;
9687 DEFVAR_LISP ("w32-grab-focus-on-raise",
9688 &Vw32_grab_focus_on_raise,
9689 "Raised frame grabs input focus.\n\
9690 When t, `raise-frame' grabs input focus as well. This fits well\n\
9691 with the normal Windows click-to-focus policy, but might not be\n\
9692 desirable when using a point-to-focus policy.");
9693 Vw32_grab_focus_on_raise = Qt;
9695 DEFVAR_LISP ("w32-capslock-is-shiftlock",
9696 &Vw32_capslock_is_shiftlock,
9697 "Apply CapsLock state to non character input keys.\n\
9698 When nil, CapsLock only affects normal character input keys.");
9699 Vw32_capslock_is_shiftlock = Qnil;
9701 DEFVAR_LISP ("w32-recognize-altgr",
9702 &Vw32_recognize_altgr,
9703 "Recognize right-alt and left-ctrl as AltGr.\n\
9704 When nil, the right-alt and left-ctrl key combination is\n\
9705 interpreted normally.");
9706 Vw32_recognize_altgr = Qt;
9708 DEFVAR_BOOL ("w32-enable-unicode-output",
9709 &w32_enable_unicode_output,
9710 "Enable the use of Unicode for text output if non-nil.\n\
9711 Unicode output may prevent some third party applications for displaying\n\
9712 Far-East Languages on Windows 95/98 from working properly.\n\
9713 NT uses Unicode internally anyway, so this flag will probably have no\n\
9714 affect on NT machines.");
9715 w32_enable_unicode_output = 1;
9717 /* VIETNAMESE_CHARSET is not defined in some versions of MSVC. */
9718 #ifndef VIETNAMESE_CHARSET
9719 #define VIETNAMESE_CHARSET 163
9720 #endif
9722 DEFVAR_LISP ("w32-charset-info-alist",
9723 &Vw32_charset_info_alist,
9724 "Alist linking Emacs character sets to Windows fonts\n\
9725 and codepages. Each entry should be of the form:\n\
9727 (CHARSET_NAME . (WINDOWS_CHARSET . CODEPAGE))\n\
9729 where CHARSET_NAME is a string used in font names to identify the charset,\n\
9730 WINDOWS_CHARSET is a symbol that can be one of:\n\
9731 w32-charset-ansi, w32-charset-default, w32-charset-symbol,\n\
9732 w32-charset-shiftjis, w32-charset-hangul, w32-charset-gb2312,\n\
9733 w32-charset-chinesebig5, "
9734 #ifdef JOHAB_CHARSET
9735 "w32-charset-johab, w32-charset-hebrew,\n\
9736 w32-charset-arabic, w32-charset-greek, w32-charset-turkish,\n\
9737 w32-charset-vietnamese, w32-charset-thai, w32-charset-easteurope,\n\
9738 w32-charset-russian, w32-charset-mac, w32-charset-baltic,\n"
9739 #endif
9740 #ifdef UNICODE_CHARSET
9741 "w32-charset-unicode, "
9742 #endif
9743 "or w32-charset-oem.\n\
9744 CODEPAGE should be an integer specifying the codepage that should be used\n\
9745 to display the character set, t to do no translation and output as Unicode,\n\
9746 or nil to do no translation and output as 8 bit (or multibyte on far-east\n\
9747 versions of Windows) characters.");
9748 Vw32_charset_info_alist = Qnil;
9750 staticpro (&Qw32_charset_ansi);
9751 Qw32_charset_ansi = intern ("w32-charset-ansi");
9752 staticpro (&Qw32_charset_symbol);
9753 Qw32_charset_symbol = intern ("w32-charset-symbol");
9754 staticpro (&Qw32_charset_shiftjis);
9755 Qw32_charset_shiftjis = intern ("w32-charset-shiftjis");
9756 staticpro (&Qw32_charset_hangul);
9757 Qw32_charset_hangul = intern ("w32-charset-hangul");
9758 staticpro (&Qw32_charset_chinesebig5);
9759 Qw32_charset_chinesebig5 = intern ("w32-charset-chinesebig5");
9760 staticpro (&Qw32_charset_gb2312);
9761 Qw32_charset_gb2312 = intern ("w32-charset-gb2312");
9762 staticpro (&Qw32_charset_oem);
9763 Qw32_charset_oem = intern ("w32-charset-oem");
9765 #ifdef JOHAB_CHARSET
9767 static int w32_extra_charsets_defined = 1;
9768 DEFVAR_BOOL ("w32-extra-charsets-defined", w32_extra_charsets_defined, "");
9770 staticpro (&Qw32_charset_johab);
9771 Qw32_charset_johab = intern ("w32-charset-johab");
9772 staticpro (&Qw32_charset_easteurope);
9773 Qw32_charset_easteurope = intern ("w32-charset-easteurope");
9774 staticpro (&Qw32_charset_turkish);
9775 Qw32_charset_turkish = intern ("w32-charset-turkish");
9776 staticpro (&Qw32_charset_baltic);
9777 Qw32_charset_baltic = intern ("w32-charset-baltic");
9778 staticpro (&Qw32_charset_russian);
9779 Qw32_charset_russian = intern ("w32-charset-russian");
9780 staticpro (&Qw32_charset_arabic);
9781 Qw32_charset_arabic = intern ("w32-charset-arabic");
9782 staticpro (&Qw32_charset_greek);
9783 Qw32_charset_greek = intern ("w32-charset-greek");
9784 staticpro (&Qw32_charset_hebrew);
9785 Qw32_charset_hebrew = intern ("w32-charset-hebrew");
9786 staticpro (&Qw32_charset_thai);
9787 Qw32_charset_thai = intern ("w32-charset-thai");
9788 staticpro (&Qw32_charset_mac);
9789 Qw32_charset_mac = intern ("w32-charset-mac");
9791 #endif
9793 #ifdef UNICODE_CHARSET
9795 static int w32_unicode_charset_defined = 1;
9796 DEFVAR_BOOL ("w32-unicode-charset-defined",
9797 w32_unicode_charset_defined, "");
9799 staticpro (&Qw32_charset_unicode);
9800 Qw32_charset_unicode = intern ("w32-charset-unicode");
9801 #endif
9803 staticpro (&help_echo);
9804 help_echo = Qnil;
9805 staticpro (&previous_help_echo);
9806 previous_help_echo = Qnil;
9808 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
9809 "*Non-nil means draw block cursor as wide as the glyph under it.\n\
9810 For example, if a block cursor is over a tab, it will be drawn as\n\
9811 wide as that tab on the display.");
9812 x_stretch_cursor_p = 0;
9814 DEFVAR_BOOL ("x-toolkit-scroll-bars-p", &x_toolkit_scroll_bars_p,
9815 "If not nil, Emacs uses toolkit scroll bars.");
9816 x_toolkit_scroll_bars_p = 1;
9818 staticpro (&last_mouse_motion_frame);
9819 last_mouse_motion_frame = Qnil;