(display_mode_element): When computing charpos, depend
[bpt/emacs.git] / src / w32term.c
1 /* Implementation of GUI terminal on the Microsoft W32 API.
2 Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GNU Emacs.
6
7 GNU Emacs is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs; see the file COPYING. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include <config.h>
23 #include <signal.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include "lisp.h"
27 #include "charset.h"
28 #include "blockinput.h"
29
30 #include "w32heap.h"
31 #include "w32term.h"
32 #include "w32bdf.h"
33 #include <shellapi.h>
34
35 #include "systty.h"
36 #include "systime.h"
37 #include "atimer.h"
38 #include "keymap.h"
39
40 #include <ctype.h>
41 #include <errno.h>
42 #include <setjmp.h>
43 #include <sys/stat.h>
44
45 #include "keyboard.h"
46 #include "frame.h"
47 #include "dispextern.h"
48 #include "fontset.h"
49 #include "termhooks.h"
50 #include "termopts.h"
51 #include "termchar.h"
52 #include "gnu.h"
53 #include "disptab.h"
54 #include "buffer.h"
55 #include "window.h"
56 #include "intervals.h"
57 #include "composite.h"
58 #include "coding.h"
59
60 #define abs(x) ((x) < 0 ? -(x) : (x))
61
62 #define BETWEEN(X, LOWER, UPPER) ((X) >= (LOWER) && (X) < (UPPER))
63
64 \f
65 /* Fringe bitmaps. */
66
67 enum fringe_bitmap_type
68 {
69 NO_FRINGE_BITMAP,
70 LEFT_TRUNCATION_BITMAP,
71 RIGHT_TRUNCATION_BITMAP,
72 OVERLAY_ARROW_BITMAP,
73 CONTINUED_LINE_BITMAP,
74 CONTINUATION_LINE_BITMAP,
75 ZV_LINE_BITMAP
76 };
77
78 /* Bitmaps are all unsigned short, as Windows requires bitmap data to
79 be Word aligned. For some reason they are horizontally reflected
80 compared to how they appear on X, so changes in xterm.c should be
81 reflected here. */
82
83 /* Bitmap drawn to indicate lines not displaying text if
84 `indicate-empty-lines' is non-nil. */
85
86 #define zv_width 8
87 #define zv_height 72
88 #define zv_period 3
89 static unsigned char zv_bits[] = {
90 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
91 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
92 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
93 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
94 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
95 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
96 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00,
97 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x3c, 0x00};
98 static HBITMAP zv_bmp;
99
100 /* An arrow like this: `<-'. */
101
102 #define left_width 8
103 #define left_height 8
104 static unsigned short left_bits[] = {
105 0x18, 0x30, 0x60, 0xfc, 0xfc, 0x60, 0x30, 0x18};
106 static HBITMAP left_bmp;
107
108 /* Right truncation arrow bitmap `->'. */
109
110 #define right_width 8
111 #define right_height 8
112 static unsigned short right_bits[] = {
113 0x18, 0x0c, 0x06, 0x3f, 0x3f, 0x06, 0x0c, 0x18};
114 static HBITMAP right_bmp;
115
116 /* Marker for continued lines. */
117
118 #define continued_width 8
119 #define continued_height 8
120 static unsigned short continued_bits[] = {
121 0x3c, 0x3e, 0x03, 0x27, 0x3f, 0x3e, 0x3c, 0x3e};
122 static HBITMAP continued_bmp;
123
124 /* Marker for continuation lines. */
125
126 #define continuation_width 8
127 #define continuation_height 8
128 static unsigned short continuation_bits[] = {
129 0x3c, 0x7c, 0xc0, 0xe4, 0xfc, 0x7c, 0x3c, 0x7c};
130 static HBITMAP continuation_bmp;
131
132 /* Overlay arrow bitmap. */
133
134 #if 0
135 /* A bomb. */
136 #define ov_width 8
137 #define ov_height 8
138 static unsigned short ov_bits[] = {
139 0x0c, 0x10, 0x3c, 0x7e, 0x5e, 0x5e, 0x46, 0x3c};
140 #else
141 /* A triangular arrow. */
142 #define ov_width 8
143 #define ov_height 8
144 static unsigned short ov_bits[] = {
145 0xc0, 0xf0, 0xf8, 0xfc, 0xfc, 0xf8, 0xf0, 0xc0};
146 #endif
147 static HBITMAP ov_bmp;
148
149 extern Lisp_Object Qhelp_echo;
150
151 \f
152 /* Non-nil means Emacs uses toolkit scroll bars. */
153
154 Lisp_Object Vx_toolkit_scroll_bars;
155
156 /* If a string, w32_read_socket generates an event to display that string.
157 (The display is done in read_char.) */
158
159 static Lisp_Object help_echo;
160 static Lisp_Object help_echo_window;
161 static Lisp_Object help_echo_object;
162 static int help_echo_pos;
163
164 /* Temporary variable for w32_read_socket. */
165
166 static Lisp_Object previous_help_echo;
167
168 /* Non-zero means that a HELP_EVENT has been generated since Emacs
169 start. */
170
171 static int any_help_event_p;
172
173 /* Non-zero means draw block and hollow cursor as wide as the glyph
174 under it. For example, if a block cursor is over a tab, it will be
175 drawn as wide as that tab on the display. */
176
177 int x_stretch_cursor_p;
178
179 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
180
181 int x_use_underline_position_properties;
182
183 extern unsigned int msh_mousewheel;
184
185 extern void free_frame_menubar ();
186
187 extern int w32_codepage_for_font (char *fontname);
188
189 extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
190 unsigned char *text, int dim);
191 extern Lisp_Object Vwindow_system;
192
193 #define x_any_window_to_frame x_window_to_frame
194 #define x_top_window_to_frame x_window_to_frame
195
196 \f
197 /* This is display since w32 does not support multiple ones. */
198 struct w32_display_info one_w32_display_info;
199 struct w32_display_info *x_display_list;
200
201 /* This is a list of cons cells, each of the form (NAME . FONT-LIST-CACHE),
202 one for each element of w32_display_list and in the same order.
203 NAME is the name of the frame.
204 FONT-LIST-CACHE records previous values returned by x-list-fonts. */
205 Lisp_Object w32_display_name_list;
206
207 /* Frame being updated by update_frame. This is declared in term.c.
208 This is set by update_begin and looked at by all the
209 w32 functions. It is zero while not inside an update.
210 In that case, the w32 functions assume that `SELECTED_FRAME ()'
211 is the frame to apply to. */
212 extern struct frame *updating_frame;
213
214 /* This is a frame waiting to be autoraised, within w32_read_socket. */
215 struct frame *pending_autoraise_frame;
216
217 /* Nominal cursor position -- where to draw output.
218 HPOS and VPOS are window relative glyph matrix coordinates.
219 X and Y are window relative pixel coordinates. */
220
221 struct cursor_pos output_cursor;
222
223 /* The handle of the frame that currently owns the system caret. */
224 HWND w32_system_caret_hwnd;
225 int w32_system_caret_width;
226 int w32_system_caret_height;
227 int w32_system_caret_x;
228 int w32_system_caret_y;
229
230 /* Flag to enable Unicode output in case users wish to use programs
231 like Twinbridge on '95 rather than installed system level support
232 for Far East languages. */
233 int w32_enable_unicode_output;
234
235 DWORD dwWindowsThreadId = 0;
236 HANDLE hWindowsThread = NULL;
237 DWORD dwMainThreadId = 0;
238 HANDLE hMainThread = NULL;
239
240 #ifndef SIF_ALL
241 /* These definitions are new with Windows 95. */
242 #define SIF_RANGE 0x0001
243 #define SIF_PAGE 0x0002
244 #define SIF_POS 0x0004
245 #define SIF_DISABLENOSCROLL 0x0008
246 #define SIF_TRACKPOS 0x0010
247 #define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
248
249 typedef struct tagSCROLLINFO
250 {
251 UINT cbSize;
252 UINT fMask;
253 int nMin;
254 int nMax;
255 UINT nPage;
256 int nPos;
257 int nTrackPos;
258 } SCROLLINFO, FAR *LPSCROLLINFO;
259 typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
260 #endif /* SIF_ALL */
261
262 /* Dynamic linking to new proportional scroll bar functions. */
263 int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
264 BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
265
266 int vertical_scroll_bar_min_handle;
267 int vertical_scroll_bar_top_border;
268 int vertical_scroll_bar_bottom_border;
269
270 int last_scroll_bar_drag_pos;
271
272 /* Mouse movement. */
273
274 /* Where the mouse was last time we reported a mouse event. */
275
276 FRAME_PTR last_mouse_frame;
277 static RECT last_mouse_glyph;
278 static Lisp_Object last_mouse_press_frame;
279
280 Lisp_Object Vw32_num_mouse_buttons;
281
282 Lisp_Object Vw32_swap_mouse_buttons;
283
284 /* Control whether x_raise_frame also sets input focus. */
285 Lisp_Object Vw32_grab_focus_on_raise;
286
287 /* Control whether Caps Lock affects non-ascii characters. */
288 Lisp_Object Vw32_capslock_is_shiftlock;
289
290 /* Control whether right-alt and left-ctrl should be recognized as AltGr. */
291 Lisp_Object Vw32_recognize_altgr;
292
293 /* The scroll bar in which the last motion event occurred.
294
295 If the last motion event occurred in a scroll bar, we set this
296 so w32_mouse_position can know whether to report a scroll bar motion or
297 an ordinary motion.
298
299 If the last motion event didn't occur in a scroll bar, we set this
300 to Qnil, to tell w32_mouse_position to return an ordinary motion event. */
301 static Lisp_Object last_mouse_scroll_bar;
302 static int last_mouse_scroll_bar_pos;
303
304 /* This is a hack. We would really prefer that w32_mouse_position would
305 return the time associated with the position it returns, but there
306 doesn't seem to be any way to wrest the time-stamp from the server
307 along with the position query. So, we just keep track of the time
308 of the last movement we received, and return that in hopes that
309 it's somewhat accurate. */
310
311 static Time last_mouse_movement_time;
312
313 /* Incremented by w32_read_socket whenever it really tries to read
314 events. */
315
316 #ifdef __STDC__
317 static int volatile input_signal_count;
318 #else
319 static int input_signal_count;
320 #endif
321
322 extern Lisp_Object Vcommand_line_args, Vsystem_name;
323
324 extern Lisp_Object Qface, Qmouse_face;
325
326 #ifndef USE_CRT_DLL
327 extern int errno;
328 #endif
329
330 /* A mask of extra modifier bits to put into every keyboard char. */
331
332 extern int extra_keyboard_modifiers;
333
334 /* Enumeration for overriding/changing the face to use for drawing
335 glyphs in x_draw_glyphs. */
336
337 enum draw_glyphs_face
338 {
339 DRAW_NORMAL_TEXT,
340 DRAW_INVERSE_VIDEO,
341 DRAW_CURSOR,
342 DRAW_MOUSE_FACE,
343 DRAW_IMAGE_RAISED,
344 DRAW_IMAGE_SUNKEN
345 };
346
347 static void x_update_window_end P_ ((struct window *, int, int));
348 static void frame_to_window_pixel_xy P_ ((struct window *, int *, int *));
349 void w32_delete_display P_ ((struct w32_display_info *));
350 static int fast_find_position P_ ((struct window *, int, int *, int *,
351 int *, int *, Lisp_Object));
352 static int fast_find_string_pos P_ ((struct window *, int, Lisp_Object,
353 int *, int *, int *, int *, int));
354 static void set_output_cursor P_ ((struct cursor_pos *));
355 static struct glyph *x_y_to_hpos_vpos P_ ((struct window *, int, int,
356 int *, int *, int *, int));
357 static void note_mode_line_highlight P_ ((struct window *, int, int));
358 static void note_mouse_highlight P_ ((struct frame *, int, int));
359 static void note_tool_bar_highlight P_ ((struct frame *f, int, int));
360 static void w32_handle_tool_bar_click P_ ((struct frame *,
361 struct input_event *));
362 static void show_mouse_face P_ ((struct w32_display_info *,
363 enum draw_glyphs_face));
364 static int cursor_in_mouse_face_p P_ ((struct window *));
365 static int clear_mouse_face P_ ((struct w32_display_info *));
366
367 void x_lower_frame P_ ((struct frame *));
368 void x_scroll_bar_clear P_ ((struct frame *));
369 void x_wm_set_size_hint P_ ((struct frame *, long, int));
370 void x_raise_frame P_ ((struct frame *));
371 void x_set_window_size P_ ((struct frame *, int, int, int));
372 void x_wm_set_window_state P_ ((struct frame *, int));
373 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
374 void w32_initialize P_ ((void));
375 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
376 int x_compute_min_glyph_bounds P_ ((struct frame *));
377 static void x_draw_phys_cursor_glyph P_ ((struct window *,
378 struct glyph_row *,
379 enum draw_glyphs_face));
380 static void x_update_end P_ ((struct frame *));
381 static void w32_frame_up_to_date P_ ((struct frame *));
382 static void w32_set_terminal_modes P_ ((void));
383 static void w32_reset_terminal_modes P_ ((void));
384 static void w32_cursor_to P_ ((int, int, int, int));
385 static void x_write_glyphs P_ ((struct glyph *, int));
386 static void x_clear_end_of_line P_ ((int));
387 static void x_clear_frame P_ ((void));
388 static void x_clear_cursor P_ ((struct window *));
389 static void frame_highlight P_ ((struct frame *));
390 static void frame_unhighlight P_ ((struct frame *));
391 static void w32_new_focus_frame P_ ((struct w32_display_info *,
392 struct frame *));
393 static void w32_frame_rehighlight P_ ((struct frame *));
394 static void x_frame_rehighlight P_ ((struct w32_display_info *));
395 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
396 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int));
397 static void expose_frame P_ ((struct frame *, int, int, int, int));
398 static int expose_window_tree P_ ((struct window *, RECT *));
399 static int expose_window P_ ((struct window *, RECT *));
400 static void expose_area P_ ((struct window *, struct glyph_row *,
401 RECT *, enum glyph_row_area));
402 static int expose_line P_ ((struct window *, struct glyph_row *,
403 RECT *));
404 void x_update_cursor P_ ((struct frame *, int));
405 static void x_update_cursor_in_window_tree P_ ((struct window *, int));
406 static void x_update_window_cursor P_ ((struct window *, int));
407 static void x_erase_phys_cursor P_ ((struct window *));
408 void x_display_cursor P_ ((struct window *w, int, int, int, int, int));
409 void x_display_and_set_cursor P_ ((struct window *, int, int, int, int, int));
410 static void w32_draw_fringe_bitmap P_ ((struct window *, HDC hdc,
411 struct glyph_row *,
412 enum fringe_bitmap_type, int left_p));
413 static void w32_clip_to_row P_ ((struct window *, struct glyph_row *,
414 HDC, int));
415 static int x_phys_cursor_in_rect_p P_ ((struct window *, RECT *));
416 static void x_draw_row_fringe_bitmaps P_ ((struct window *,
417 struct glyph_row *));
418 static void notice_overwritten_cursor P_ ((struct window *,
419 enum glyph_row_area,
420 int, int, int, int));
421
422 static Lisp_Object Qvendor_specific_keysyms;
423
424 \f
425 /***********************************************************************
426 Debugging
427 ***********************************************************************/
428
429 #if 0
430
431 /* This is a function useful for recording debugging information about
432 the sequence of occurrences in this file. */
433
434 struct record
435 {
436 char *locus;
437 int type;
438 };
439
440 struct record event_record[100];
441
442 int event_record_index;
443
444 record_event (locus, type)
445 char *locus;
446 int type;
447 {
448 if (event_record_index == sizeof (event_record) / sizeof (struct record))
449 event_record_index = 0;
450
451 event_record[event_record_index].locus = locus;
452 event_record[event_record_index].type = type;
453 event_record_index++;
454 }
455
456 #endif /* 0 */
457 \f
458
459 void XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
460 XGCValues *xgcv)
461 {
462 if (mask & GCForeground)
463 gc->foreground = xgcv->foreground;
464 if (mask & GCBackground)
465 gc->background = xgcv->background;
466 if (mask & GCFont)
467 gc->font = xgcv->font;
468 }
469
470 XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
471 XGCValues *xgcv)
472 {
473 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
474 bzero (gc, sizeof (XGCValues));
475
476 XChangeGC (ignore, gc, mask, xgcv);
477
478 return gc;
479 }
480
481 void XGetGCValues (void* ignore, XGCValues *gc,
482 unsigned long mask, XGCValues *xgcv)
483 {
484 XChangeGC (ignore, xgcv, mask, gc);
485 }
486
487 static void
488 w32_set_clip_rectangle (HDC hdc, RECT *rect)
489 {
490 if (rect)
491 {
492 HRGN clip_region = CreateRectRgnIndirect (rect);
493 SelectClipRgn (hdc, clip_region);
494 DeleteObject (clip_region);
495 }
496 else
497 SelectClipRgn (hdc, NULL);
498 }
499
500
501 /* Draw a hollow rectangle at the specified position. */
502 void
503 w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
504 int width, int height)
505 {
506 HBRUSH hb, oldhb;
507 HPEN hp, oldhp;
508
509 hb = CreateSolidBrush (gc->background);
510 hp = CreatePen (PS_SOLID, 0, gc->foreground);
511 oldhb = SelectObject (hdc, hb);
512 oldhp = SelectObject (hdc, hp);
513
514 Rectangle (hdc, x, y, x + width, y + height);
515
516 SelectObject (hdc, oldhb);
517 SelectObject (hdc, oldhp);
518 DeleteObject (hb);
519 DeleteObject (hp);
520 }
521
522 /* Draw a filled rectangle at the specified position. */
523 void
524 w32_fill_rect (f, hdc, pix, lprect)
525 FRAME_PTR f;
526 HDC hdc;
527 COLORREF pix;
528 RECT * lprect;
529 {
530 HBRUSH hb;
531
532 hb = CreateSolidBrush (pix);
533 FillRect (hdc, lprect, hb);
534 DeleteObject (hb);
535 }
536
537 void
538 w32_clear_window (f)
539 FRAME_PTR f;
540 {
541 RECT rect;
542 HDC hdc = get_frame_dc (f);
543
544 /* Under certain conditions, this can be called at startup with
545 a console frame pointer before the GUI frame is created. An HDC
546 of 0 indicates this. */
547 if (hdc)
548 {
549 GetClientRect (FRAME_W32_WINDOW (f), &rect);
550 w32_clear_rect (f, hdc, &rect);
551 }
552
553 release_frame_dc (f, hdc);
554 }
555
556 \f
557 /***********************************************************************
558 Starting and ending an update
559 ***********************************************************************/
560
561 /* Start an update of frame F. This function is installed as a hook
562 for update_begin, i.e. it is called when update_begin is called.
563 This function is called prior to calls to x_update_window_begin for
564 each window being updated. */
565
566 static void
567 x_update_begin (f)
568 struct frame *f;
569 {
570 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
571
572 if (! FRAME_W32_P (f))
573 return;
574
575 /* Regenerate display palette before drawing if list of requested
576 colors has changed. */
577 if (display_info->regen_palette)
578 {
579 w32_regenerate_palette (f);
580 display_info->regen_palette = FALSE;
581 }
582 }
583
584
585 /* Start update of window W. Set the global variable updated_window
586 to the window being updated and set output_cursor to the cursor
587 position of W. */
588
589 static void
590 x_update_window_begin (w)
591 struct window *w;
592 {
593 struct frame *f = XFRAME (WINDOW_FRAME (w));
594 struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
595
596 updated_window = w;
597 set_output_cursor (&w->cursor);
598
599 BLOCK_INPUT;
600
601 if (f == display_info->mouse_face_mouse_frame)
602 {
603 /* Don't do highlighting for mouse motion during the update. */
604 display_info->mouse_face_defer = 1;
605
606 /* If F needs to be redrawn, simply forget about any prior mouse
607 highlighting. */
608 if (FRAME_GARBAGED_P (f))
609 display_info->mouse_face_window = Qnil;
610
611 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
612 their mouse_face_p flag set, which means that they are always
613 unequal to rows in a desired matrix which never have that
614 flag set. So, rows containing mouse-face glyphs are never
615 scrolled, and we don't have to switch the mouse highlight off
616 here to prevent it from being scrolled. */
617
618 /* Can we tell that this update does not affect the window
619 where the mouse highlight is? If so, no need to turn off.
620 Likewise, don't do anything if the frame is garbaged;
621 in that case, the frame's current matrix that we would use
622 is all wrong, and we will redisplay that line anyway. */
623 if (!NILP (display_info->mouse_face_window)
624 && w == XWINDOW (display_info->mouse_face_window))
625 {
626 int i;
627
628 for (i = 0; i < w->desired_matrix->nrows; ++i)
629 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
630 break;
631
632 if (i < w->desired_matrix->nrows)
633 clear_mouse_face (display_info);
634 }
635 #endif /* 0 */
636 }
637
638 UNBLOCK_INPUT;
639 }
640
641
642 /* Draw a vertical window border to the right of window W if W doesn't
643 have vertical scroll bars. */
644
645 static void
646 x_draw_vertical_border (w)
647 struct window *w;
648 {
649 struct frame *f = XFRAME (WINDOW_FRAME (w));
650
651 /* Redraw borders between horizontally adjacent windows. Don't
652 do it for frames with vertical scroll bars because either the
653 right scroll bar of a window, or the left scroll bar of its
654 neighbor will suffice as a border. */
655 if (!WINDOW_RIGHTMOST_P (w)
656 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
657 {
658 RECT r;
659 HDC hdc;
660
661 window_box_edges (w, -1, (int *) &r.left, (int *) &r.top,
662 (int *) &r.right, (int *) &r.bottom);
663 r.left = r.right + FRAME_X_RIGHT_FRINGE_WIDTH (f);
664 r.right = r.left + 1;
665 r.bottom -= 1;
666
667 hdc = get_frame_dc (f);
668 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
669 release_frame_dc (f, hdc);
670 }
671 }
672
673
674 /* End update of window W (which is equal to updated_window).
675
676 Draw vertical borders between horizontally adjacent windows, and
677 display W's cursor if CURSOR_ON_P is non-zero.
678
679 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
680 glyphs in mouse-face were overwritten. In that case we have to
681 make sure that the mouse-highlight is properly redrawn.
682
683 W may be a menu bar pseudo-window in case we don't have X toolkit
684 support. Such windows don't have a cursor, so don't display it
685 here. */
686
687 static void
688 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
689 struct window *w;
690 int cursor_on_p, mouse_face_overwritten_p;
691 {
692 struct w32_display_info *dpyinfo
693 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
694
695 if (!w->pseudo_window_p)
696 {
697 BLOCK_INPUT;
698
699 if (cursor_on_p)
700 x_display_and_set_cursor (w, 1, output_cursor.hpos,
701 output_cursor.vpos,
702 output_cursor.x, output_cursor.y);
703
704 x_draw_vertical_border (w);
705 UNBLOCK_INPUT;
706 }
707
708 /* If a row with mouse-face was overwritten, arrange for
709 XTframe_up_to_date to redisplay the mouse highlight. */
710 if (mouse_face_overwritten_p)
711 {
712 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
713 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
714 dpyinfo->mouse_face_window = Qnil;
715 }
716
717 updated_window = NULL;
718 }
719
720
721 /* End update of frame F. This function is installed as a hook in
722 update_end. */
723
724 static void
725 x_update_end (f)
726 struct frame *f;
727 {
728 if (! FRAME_W32_P (f))
729 return;
730
731 /* Mouse highlight may be displayed again. */
732 FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
733 }
734
735
736 /* This function is called from various places in xdisp.c whenever a
737 complete update has been performed. The global variable
738 updated_window is not available here. */
739
740 static void
741 w32_frame_up_to_date (f)
742 struct frame *f;
743 {
744 if (FRAME_W32_P (f))
745 {
746 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
747 if (dpyinfo->mouse_face_deferred_gc
748 || f == dpyinfo->mouse_face_mouse_frame)
749 {
750 BLOCK_INPUT;
751 if (dpyinfo->mouse_face_mouse_frame)
752 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
753 dpyinfo->mouse_face_mouse_x,
754 dpyinfo->mouse_face_mouse_y);
755 dpyinfo->mouse_face_deferred_gc = 0;
756 UNBLOCK_INPUT;
757 }
758 }
759 }
760
761
762 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
763 arrow bitmaps, or clear the fringes if no bitmaps are required
764 before DESIRED_ROW is made current. The window being updated is
765 found in updated_window. This function is called from
766 update_window_line only if it is known that there are differences
767 between bitmaps to be drawn between current row and DESIRED_ROW. */
768
769 static void
770 x_after_update_window_line (desired_row)
771 struct glyph_row *desired_row;
772 {
773 struct window *w = updated_window;
774 struct frame *f;
775 int width, height;
776
777 xassert (w);
778
779 if (!desired_row->mode_line_p && !w->pseudo_window_p)
780 {
781 BLOCK_INPUT;
782 x_draw_row_fringe_bitmaps (w, desired_row);
783 UNBLOCK_INPUT;
784 }
785
786 /* When a window has disappeared, make sure that no rest of
787 full-width rows stays visible in the internal border. Could
788 check here if updated_window is the leftmost/rightmost window,
789 but I guess it's not worth doing since vertically split windows
790 are almost never used, internal border is rarely set, and the
791 overhead is very small. */
792 if (windows_or_buffers_changed
793 && desired_row->full_width_p
794 && (f = XFRAME (w->frame),
795 width = FRAME_INTERNAL_BORDER_WIDTH (f),
796 width != 0)
797 && (height = desired_row->visible_height,
798 height > 0))
799 {
800 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
801 /* Internal border is drawn below the tool bar. */
802 if (WINDOWP (f->tool_bar_window)
803 && w == XWINDOW (f->tool_bar_window))
804 y -= width;
805
806 BLOCK_INPUT;
807 {
808 HDC hdc = get_frame_dc (f);
809 w32_clear_area (f, hdc, 0, y, width, height);
810 w32_clear_area (f, hdc, f->output_data.w32->pixel_width - width,
811 y, width, height);
812 release_frame_dc (f, hdc);
813 }
814 UNBLOCK_INPUT;
815 }
816 }
817
818
819 /* Draw the bitmap WHICH in one of the left or right fringes of
820 window W. ROW is the glyph row for which to display the bitmap; it
821 determines the vertical position at which the bitmap has to be
822 drawn. */
823
824 static void
825 w32_draw_fringe_bitmap (w, hdc, row, which, left_p)
826 struct window *w;
827 HDC hdc;
828 struct glyph_row *row;
829 enum fringe_bitmap_type which;
830 int left_p;
831 {
832 struct frame *f = XFRAME (WINDOW_FRAME (w));
833 Window window = FRAME_W32_WINDOW (f);
834 HDC compat_hdc;
835 int x, y, wd, h, dy;
836 int b1, b2;
837 HBITMAP pixmap;
838 HANDLE horig_obj;
839 struct face *face;
840
841 /* Must clip because of partially visible lines. */
842 w32_clip_to_row (w, row, hdc, 1);
843
844 /* Convert row to frame coordinates. */
845 y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
846
847 switch (which)
848 {
849 case NO_FRINGE_BITMAP:
850 wd = 0;
851 h = 0;
852 break;
853
854 case LEFT_TRUNCATION_BITMAP:
855 wd = left_width;
856 h = left_height;
857 pixmap = left_bmp;
858 break;
859
860 case OVERLAY_ARROW_BITMAP:
861 wd = ov_width;
862 h = ov_height;
863 pixmap = ov_bmp;
864 break;
865
866 case RIGHT_TRUNCATION_BITMAP:
867 wd = right_width;
868 h = right_height;
869 pixmap = right_bmp;
870 break;
871
872 case CONTINUED_LINE_BITMAP:
873 wd = continued_width;
874 h = continued_height;
875 pixmap = continued_bmp;
876 break;
877
878 case CONTINUATION_LINE_BITMAP:
879 wd = continuation_width;
880 h = continuation_height;
881 pixmap = continuation_bmp;
882 break;
883
884 case ZV_LINE_BITMAP:
885 wd = zv_width;
886 h = zv_height - (y % zv_period);
887 pixmap = zv_bmp;
888 break;
889
890 default:
891 abort ();
892 }
893
894 /* Clip bitmap if too high. */
895 if (h > row->height)
896 h = row->height;
897
898 /* Set dy to the offset in the row to start drawing the bitmap. */
899 dy = (row->height - h) / 2;
900
901 /* Draw the bitmap. */
902 face = FACE_FROM_ID (f, FRINGE_FACE_ID);
903 PREPARE_FACE_FOR_DISPLAY (f, face);
904
905 /* Clear left fringe if no bitmap to draw or if bitmap doesn't fill
906 the fringe. */
907 b1 = -1;
908 if (left_p)
909 {
910 if (wd > FRAME_X_LEFT_FRINGE_WIDTH (f))
911 wd = FRAME_X_LEFT_FRINGE_WIDTH (f);
912 x = (WINDOW_TO_FRAME_PIXEL_X (w, 0)
913 - wd
914 - (FRAME_X_LEFT_FRINGE_WIDTH (f) - wd) / 2);
915 if (wd < FRAME_X_LEFT_FRINGE_WIDTH (f) || row->height > h)
916 {
917 /* If W has a vertical border to its left, don't draw over it. */
918 int border = ((XFASTINT (w->left) > 0
919 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
920 ? 1 : 0);
921 b1 = (window_box_left (w, -1)
922 - FRAME_X_LEFT_FRINGE_WIDTH (f)
923 + border);
924 b2 = (FRAME_X_LEFT_FRINGE_WIDTH (f) - border);
925 }
926 }
927 else
928 {
929 if (wd > FRAME_X_RIGHT_FRINGE_WIDTH (f))
930 wd = FRAME_X_RIGHT_FRINGE_WIDTH (f);
931 x = (window_box_right (w, -1)
932 + (FRAME_X_RIGHT_FRINGE_WIDTH (f) - wd) / 2);
933 /* Clear right fringe if no bitmap to draw of if bitmap doesn't fill
934 the fringe. */
935 if (wd < FRAME_X_RIGHT_FRINGE_WIDTH (f) || row->height > h)
936 {
937 b1 = window_box_right (w, -1);
938 b2 = FRAME_X_RIGHT_FRINGE_WIDTH (f);
939 }
940 }
941
942 if (b1 >= 0)
943 {
944 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
945
946 w32_fill_area (f, hdc, face->background,
947 b1,
948 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
949 row->y)),
950 b2,
951 row->visible_height);
952 }
953
954 if (which == NO_FRINGE_BITMAP)
955 return;
956
957 compat_hdc = CreateCompatibleDC (hdc);
958 SaveDC (hdc);
959
960 horig_obj = SelectObject (compat_hdc, pixmap);
961 SetTextColor (hdc, face->background);
962 SetBkColor (hdc, face->foreground);
963
964 BitBlt (hdc, x, y + dy, wd, h, compat_hdc, 0,
965 (which == ZV_LINE_BITMAP ? (row->y % zv_period) : 0),
966 SRCCOPY);
967
968 SelectObject (compat_hdc, horig_obj);
969 DeleteDC (compat_hdc);
970 RestoreDC (hdc, -1);
971 }
972
973
974 /* Draw fringe bitmaps for glyph row ROW on window W. Call this
975 function with input blocked. */
976
977 static void
978 x_draw_row_fringe_bitmaps (w, row)
979 struct window *w;
980 struct glyph_row *row;
981 {
982 struct frame *f = XFRAME (w->frame);
983 enum fringe_bitmap_type bitmap;
984 HDC hdc;
985
986 xassert (interrupt_input_blocked);
987
988 /* If row is completely invisible, because of vscrolling, we
989 don't have to draw anything. */
990 if (row->visible_height <= 0)
991 return;
992
993 hdc = get_frame_dc (f);
994
995 if (FRAME_X_LEFT_FRINGE_WIDTH (f) != 0)
996 {
997 /* Decide which bitmap to draw in the left fringe. */
998 if (row->overlay_arrow_p)
999 bitmap = OVERLAY_ARROW_BITMAP;
1000 else if (row->truncated_on_left_p)
1001 bitmap = LEFT_TRUNCATION_BITMAP;
1002 else if (MATRIX_ROW_CONTINUATION_LINE_P (row))
1003 bitmap = CONTINUATION_LINE_BITMAP;
1004 else if (row->indicate_empty_line_p)
1005 bitmap = ZV_LINE_BITMAP;
1006 else
1007 bitmap = NO_FRINGE_BITMAP;
1008
1009 w32_draw_fringe_bitmap (w, hdc, row, bitmap, 1);
1010 }
1011
1012 if (FRAME_X_RIGHT_FRINGE_WIDTH (f) != 0)
1013 {
1014 /* Decide which bitmap to draw in the right fringe. */
1015 if (row->truncated_on_right_p)
1016 bitmap = RIGHT_TRUNCATION_BITMAP;
1017 else if (row->continued_p)
1018 bitmap = CONTINUED_LINE_BITMAP;
1019 else if (row->indicate_empty_line_p && FRAME_X_LEFT_FRINGE_WIDTH (f) == 0)
1020 bitmap = ZV_LINE_BITMAP;
1021 else
1022 bitmap = NO_FRINGE_BITMAP;
1023
1024 w32_draw_fringe_bitmap (w, hdc, row, bitmap, 0);
1025 }
1026
1027 release_frame_dc (f, hdc);
1028 }
1029
1030 \f
1031 /* This is called when starting Emacs and when restarting after
1032 suspend. When starting Emacs, no window is mapped. And nothing
1033 must be done to Emacs's own window if it is suspended (though that
1034 rarely happens). */
1035
1036 static void
1037 w32_set_terminal_modes (void)
1038 {
1039 }
1040
1041 /* This is called when exiting or suspending Emacs. Exiting will make
1042 the W32 windows go away, and suspending requires no action. */
1043
1044 static void
1045 w32_reset_terminal_modes (void)
1046 {
1047 }
1048
1049
1050 \f
1051 /***********************************************************************
1052 Output Cursor
1053 ***********************************************************************/
1054
1055 /* Set the global variable output_cursor to CURSOR. All cursor
1056 positions are relative to updated_window. */
1057
1058 static void
1059 set_output_cursor (cursor)
1060 struct cursor_pos *cursor;
1061 {
1062 output_cursor.hpos = cursor->hpos;
1063 output_cursor.vpos = cursor->vpos;
1064 output_cursor.x = cursor->x;
1065 output_cursor.y = cursor->y;
1066 }
1067
1068
1069 /* Set a nominal cursor position.
1070
1071 HPOS and VPOS are column/row positions in a window glyph matrix. X
1072 and Y are window text area relative pixel positions.
1073
1074 If this is done during an update, updated_window will contain the
1075 window that is being updated and the position is the future output
1076 cursor position for that window. If updated_window is null, use
1077 selected_window and display the cursor at the given position. */
1078
1079 static void
1080 w32_cursor_to (vpos, hpos, y, x)
1081 int vpos, hpos, y, x;
1082 {
1083 struct window *w;
1084
1085 /* If updated_window is not set, work on selected_window. */
1086 if (updated_window)
1087 w = updated_window;
1088 else
1089 w = XWINDOW (selected_window);
1090
1091 /* Set the output cursor. */
1092 output_cursor.hpos = hpos;
1093 output_cursor.vpos = vpos;
1094 output_cursor.x = x;
1095 output_cursor.y = y;
1096
1097 /* If not called as part of an update, really display the cursor.
1098 This will also set the cursor position of W. */
1099 if (updated_window == NULL)
1100 {
1101 BLOCK_INPUT;
1102 x_display_cursor (w, 1, hpos, vpos, x, y);
1103 UNBLOCK_INPUT;
1104 }
1105 }
1106
1107
1108 \f
1109 /***********************************************************************
1110 Display Iterator
1111 ***********************************************************************/
1112
1113 /* Function prototypes of this page. */
1114
1115 static struct face *x_get_glyph_face_and_encoding P_ ((struct frame *,
1116 struct glyph *,
1117 wchar_t *,
1118 int *));
1119 static struct face *x_get_char_face_and_encoding P_ ((struct frame *, int,
1120 int, wchar_t *, int));
1121 static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
1122 wchar_t *,
1123 enum w32_char_font_type));
1124 static enum w32_char_font_type
1125 w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
1126 static void x_append_glyph P_ ((struct it *));
1127 static void x_append_composite_glyph P_ ((struct it *));
1128 static void x_append_stretch_glyph P_ ((struct it *it, Lisp_Object,
1129 int, int, double));
1130 static void x_produce_glyphs P_ ((struct it *));
1131 static void x_produce_image_glyph P_ ((struct it *it));
1132
1133
1134 /* Dealing with bits of wchar_t as if they were an XChar2B. */
1135 #define BUILD_WCHAR_T(byte1, byte2) \
1136 ((wchar_t)((((byte1) & 0x00ff) << 8) | ((byte2) & 0x00ff)))
1137
1138
1139 #define BYTE1(ch) \
1140 (((ch) & 0xff00) >> 8)
1141
1142 #define BYTE2(ch) \
1143 ((ch) & 0x00ff)
1144
1145
1146 /* Get metrics of character CHAR2B in FONT. Value is always non-null.
1147 If CHAR2B is not contained in FONT, the font's default character
1148 metric is returned. */
1149
1150 static int
1151 w32_bdf_per_char_metric (font, char2b, dim, pcm)
1152 XFontStruct *font;
1153 wchar_t *char2b;
1154 int dim;
1155 XCharStruct * pcm;
1156 {
1157 glyph_metric * bdf_metric;
1158 char buf[2];
1159
1160 if (dim == 1)
1161 buf[0] = (char)(*char2b);
1162 else
1163 {
1164 buf[0] = BYTE1 (*char2b);
1165 buf[1] = BYTE2 (*char2b);
1166 }
1167
1168 bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
1169
1170 if (bdf_metric)
1171 {
1172 pcm->width = bdf_metric->dwidth;
1173 pcm->lbearing = bdf_metric->bbox;
1174 pcm->rbearing = bdf_metric->dwidth
1175 - (bdf_metric->bbox + bdf_metric->bbw);
1176 pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
1177 pcm->descent = -bdf_metric->bboy;
1178
1179 return 1;
1180 }
1181 return 0;
1182 }
1183
1184
1185 static int
1186 w32_native_per_char_metric (font, char2b, font_type, pcm)
1187 XFontStruct *font;
1188 wchar_t *char2b;
1189 enum w32_char_font_type font_type;
1190 XCharStruct * pcm;
1191 {
1192 HDC hdc = GetDC (NULL);
1193 HFONT old_font;
1194 BOOL retval = FALSE;
1195
1196 xassert (font && char2b);
1197 xassert (font->hfont);
1198 xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
1199
1200 old_font = SelectObject (hdc, font->hfont);
1201
1202 if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
1203 {
1204 ABC char_widths;
1205
1206 if (font_type == UNICODE_FONT)
1207 retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
1208 else
1209 retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
1210
1211 if (retval)
1212 {
1213 pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
1214 pcm->lbearing = char_widths.abcA;
1215 pcm->rbearing = pcm->width - char_widths.abcC;
1216 pcm->ascent = FONT_BASE (font);
1217 pcm->descent = FONT_DESCENT (font);
1218 }
1219 }
1220
1221 if (!retval)
1222 {
1223 /* Either font is not a True-type font, or GetCharABCWidthsW
1224 failed (it is not supported on Windows 9x for instance), so we
1225 can't determine the full info we would like. All is not lost
1226 though - we can call GetTextExtentPoint32 to get rbearing and
1227 deduce width based on the font's per-string overhang. lbearing
1228 is assumed to be zero. */
1229
1230 /* TODO: Some Thai characters (and other composites if Windows
1231 supports them) do have lbearing, and report their total width
1232 as zero. Need some way of handling them when
1233 GetCharABCWidthsW fails. */
1234 SIZE sz;
1235
1236 if (font_type == UNICODE_FONT)
1237 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
1238 else
1239 retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
1240
1241 if (retval)
1242 {
1243 pcm->width = sz.cx - font->tm.tmOverhang;
1244 pcm->rbearing = sz.cx;
1245 pcm->lbearing = 0;
1246 pcm->ascent = FONT_BASE (font);
1247 pcm->descent = FONT_DESCENT (font);
1248 }
1249 }
1250
1251
1252 if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
1253 {
1254 retval = FALSE;
1255 }
1256
1257 SelectObject (hdc, old_font);
1258 ReleaseDC (NULL, hdc);
1259
1260 return retval;
1261 }
1262
1263
1264 static XCharStruct *
1265 w32_per_char_metric (font, char2b, font_type)
1266 XFontStruct *font;
1267 wchar_t *char2b;
1268 enum w32_char_font_type font_type;
1269 {
1270 /* The result metric information. */
1271 XCharStruct *pcm;
1272 BOOL retval;
1273
1274 xassert (font && char2b);
1275 xassert (font_type != UNKNOWN_FONT);
1276
1277 /* Handle the common cases quickly. */
1278 if (!font->bdf && font->per_char == NULL)
1279 /* TODO: determine whether char2b exists in font? */
1280 return &font->max_bounds;
1281 else if (!font->bdf && *char2b < 128)
1282 return &font->per_char[*char2b];
1283
1284 pcm = &font->scratch;
1285
1286 if (font_type == BDF_1D_FONT)
1287 retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
1288 else if (font_type == BDF_2D_FONT)
1289 retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
1290 else
1291 retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
1292
1293 if (retval)
1294 return pcm;
1295
1296 return NULL;
1297 }
1298
1299 void
1300 w32_cache_char_metrics (font)
1301 XFontStruct *font;
1302 {
1303 wchar_t char2b = L'x';
1304
1305 /* Cache char metrics for the common cases. */
1306 if (font->bdf)
1307 {
1308 /* TODO: determine whether font is fixed-pitch. */
1309 if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
1310 {
1311 /* Use the font width and height as max bounds, as not all BDF
1312 fonts contain the letter 'x'. */
1313 font->max_bounds.width = FONT_MAX_WIDTH (font);
1314 font->max_bounds.lbearing = -font->bdf->llx;
1315 font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
1316 font->max_bounds.ascent = FONT_BASE (font);
1317 font->max_bounds.descent = FONT_DESCENT (font);
1318 }
1319 }
1320 else
1321 {
1322 if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
1323 /* Some fonts (eg DBCS fonts) are marked as fixed width even
1324 though they contain characters of different widths. */
1325 || (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
1326 {
1327 /* Font is not fixed pitch, so cache per_char info for the
1328 ASCII characters. It would be much more work, and probably
1329 not worth it, to cache other chars, since we may change
1330 between using Unicode and ANSI text drawing functions at
1331 run-time. */
1332 int i;
1333
1334 font->per_char = xmalloc (128 * sizeof(XCharStruct));
1335 for (i = 0; i < 128; i++)
1336 {
1337 char2b = i;
1338 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1339 &font->per_char[i]);
1340 }
1341 }
1342 else
1343 w32_native_per_char_metric (font, &char2b, ANSI_FONT,
1344 &font->max_bounds);
1345 }
1346 }
1347
1348
1349 /* Determine if a font is double byte. */
1350 int w32_font_is_double_byte (XFontStruct *font)
1351 {
1352 return font->double_byte_p;
1353 }
1354
1355
1356 static BOOL
1357 w32_use_unicode_for_codepage (codepage)
1358 int codepage;
1359 {
1360 /* If the current codepage is supported, use Unicode for output. */
1361 return (w32_enable_unicode_output
1362 && codepage != CP_8BIT
1363 && (codepage == CP_UNICODE || IsValidCodePage (codepage)));
1364 }
1365
1366 /* Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1367 the two-byte form of C. Encoding is returned in *CHAR2B. */
1368
1369 static INLINE enum w32_char_font_type
1370 w32_encode_char (c, char2b, font_info, two_byte_p)
1371 int c;
1372 wchar_t *char2b;
1373 struct font_info *font_info;
1374 int * two_byte_p;
1375 {
1376 int charset = CHAR_CHARSET (c);
1377 int codepage;
1378 int unicode_p = 0;
1379
1380 XFontStruct *font = font_info->font;
1381
1382 xassert (two_byte_p);
1383
1384 *two_byte_p = w32_font_is_double_byte (font);
1385
1386 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1387 This may be either a program in a special encoder language or a
1388 fixed encoding. */
1389 if (font_info->font_encoder)
1390 {
1391 /* It's a program. */
1392 struct ccl_program *ccl = font_info->font_encoder;
1393
1394 if (CHARSET_DIMENSION (charset) == 1)
1395 {
1396 ccl->reg[0] = charset;
1397 ccl->reg[1] = BYTE2 (*char2b);
1398 }
1399 else
1400 {
1401 ccl->reg[0] = charset;
1402 ccl->reg[1] = BYTE1 (*char2b);
1403 ccl->reg[2] = BYTE2 (*char2b);
1404 }
1405
1406 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1407
1408 /* We assume that MSBs are appropriately set/reset by CCL
1409 program. */
1410 if (!*two_byte_p) /* 1-byte font */
1411 *char2b = BUILD_WCHAR_T (0, ccl->reg[1]);
1412 else
1413 *char2b = BUILD_WCHAR_T (ccl->reg[1], ccl->reg[2]);
1414 }
1415 else if (font_info->encoding[charset])
1416 {
1417 /* Fixed encoding scheme. See fontset.h for the meaning of the
1418 encoding numbers. */
1419 int enc = font_info->encoding[charset];
1420
1421 if ((enc == 1 || enc == 2)
1422 && CHARSET_DIMENSION (charset) == 2)
1423 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b) | 0x80, BYTE2 (*char2b));
1424
1425 if (enc == 1 || enc == 3
1426 || (enc == 4 && CHARSET_DIMENSION (charset) == 1))
1427 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), BYTE2 (*char2b) | 0x80);
1428 else if (enc == 4)
1429 {
1430 int sjis1, sjis2;
1431
1432 ENCODE_SJIS (BYTE1 (*char2b), BYTE2 (*char2b),
1433 sjis1, sjis2);
1434 *char2b = BUILD_WCHAR_T (sjis1, sjis2);
1435 }
1436 }
1437 codepage = font_info->codepage;
1438
1439 /* If charset is not ASCII or Latin-1, may need to move it into
1440 Unicode space. */
1441 if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
1442 && charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
1443 && charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
1444 {
1445 char temp[3];
1446 temp[0] = BYTE1 (*char2b);
1447 temp[1] = BYTE2 (*char2b);
1448 temp[2] = '\0';
1449 if (codepage != CP_UNICODE)
1450 {
1451 if (temp[0])
1452 MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
1453 else
1454 MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
1455 }
1456 unicode_p = 1;
1457 *two_byte_p = 1;
1458 }
1459 if (!font)
1460 return UNKNOWN_FONT;
1461 else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
1462 return BDF_1D_FONT;
1463 else if (font->bdf)
1464 return BDF_2D_FONT;
1465 else if (unicode_p)
1466 return UNICODE_FONT;
1467 else
1468 return ANSI_FONT;
1469 }
1470
1471
1472 /* Get face and two-byte form of character C in face FACE_ID on frame
1473 F. The encoding of C is returned in *CHAR2B. MULTIBYTE_P non-zero
1474 means we want to display multibyte text. Value is a pointer to a
1475 realized face that is ready for display. */
1476
1477 static INLINE struct face *
1478 x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1479 struct frame *f;
1480 int c, face_id;
1481 wchar_t *char2b;
1482 int multibyte_p;
1483 {
1484 struct face *face = FACE_FROM_ID (f, face_id);
1485
1486 if (!multibyte_p)
1487 {
1488 /* Unibyte case. We don't have to encode, but we have to make
1489 sure to use a face suitable for unibyte. */
1490 *char2b = BUILD_WCHAR_T (0, c);
1491 face_id = FACE_FOR_CHAR (f, face, c);
1492 face = FACE_FROM_ID (f, face_id);
1493 }
1494 else if (c < 128 && face_id < BASIC_FACE_ID_SENTINEL)
1495 {
1496 /* Case of ASCII in a face known to fit ASCII. */
1497 *char2b = BUILD_WCHAR_T (0, c);
1498 }
1499 else
1500 {
1501 int c1, c2, charset;
1502
1503 /* Split characters into bytes. If c2 is -1 afterwards, C is
1504 really a one-byte character so that byte1 is zero. */
1505 SPLIT_CHAR (c, charset, c1, c2);
1506 if (c2 > 0)
1507 *char2b = BUILD_WCHAR_T (c1, c2);
1508 else
1509 *char2b = BUILD_WCHAR_T (0, c1);
1510
1511 /* Maybe encode the character in *CHAR2B. */
1512 if (face->font != NULL)
1513 {
1514 struct font_info *font_info
1515 = FONT_INFO_FROM_ID (f, face->font_info_id);
1516 if (font_info)
1517 w32_encode_char (c, char2b, font_info, &multibyte_p);
1518 }
1519 }
1520
1521 /* Make sure X resources of the face are allocated. */
1522 xassert (face != NULL);
1523 PREPARE_FACE_FOR_DISPLAY (f, face);
1524
1525 return face;
1526 }
1527
1528
1529 /* Get face and two-byte form of character glyph GLYPH on frame F.
1530 The encoding of GLYPH->u.ch is returned in *CHAR2B. Value is
1531 a pointer to a realized face that is ready for display. */
1532
1533 static INLINE struct face *
1534 x_get_glyph_face_and_encoding (f, glyph, char2b, two_byte_p)
1535 struct frame *f;
1536 struct glyph *glyph;
1537 wchar_t *char2b;
1538 int *two_byte_p;
1539 {
1540 struct face *face;
1541 int dummy = 0;
1542
1543 xassert (glyph->type == CHAR_GLYPH);
1544 face = FACE_FROM_ID (f, glyph->face_id);
1545
1546 if (two_byte_p)
1547 *two_byte_p = 0;
1548 else
1549 two_byte_p = &dummy;
1550
1551 if (!glyph->multibyte_p)
1552 {
1553 /* Unibyte case. We don't have to encode, but we have to make
1554 sure to use a face suitable for unibyte. */
1555 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1556 }
1557 else if (glyph->u.ch < 128
1558 && glyph->face_id < BASIC_FACE_ID_SENTINEL)
1559 {
1560 /* Case of ASCII in a face known to fit ASCII. */
1561 *char2b = BUILD_WCHAR_T (0, glyph->u.ch);
1562 }
1563 else
1564 {
1565 int c1, c2, charset;
1566
1567 /* Split characters into bytes. If c2 is -1 afterwards, C is
1568 really a one-byte character so that byte1 is zero. */
1569 SPLIT_CHAR (glyph->u.ch, charset, c1, c2);
1570 if (c2 > 0)
1571 *char2b = BUILD_WCHAR_T (c1, c2);
1572 else
1573 *char2b = BUILD_WCHAR_T (0, c1);
1574
1575 /* Maybe encode the character in *CHAR2B. */
1576 if (charset != CHARSET_ASCII)
1577 {
1578 struct font_info *font_info
1579 = FONT_INFO_FROM_ID (f, face->font_info_id);
1580 if (font_info)
1581 {
1582 glyph->w32_font_type
1583 = w32_encode_char (glyph->u.ch, char2b, font_info, two_byte_p);
1584 }
1585 }
1586 }
1587
1588 /* Make sure X resources of the face are allocated. */
1589 xassert (face != NULL);
1590 PREPARE_FACE_FOR_DISPLAY (f, face);
1591 return face;
1592 }
1593
1594
1595 /* Store one glyph for IT->char_to_display in IT->glyph_row.
1596 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1597
1598 static INLINE void
1599 x_append_glyph (it)
1600 struct it *it;
1601 {
1602 struct glyph *glyph;
1603 enum glyph_row_area area = it->area;
1604
1605 xassert (it->glyph_row);
1606 xassert (it->char_to_display != '\n' && it->char_to_display != '\t');
1607
1608 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1609 if (glyph < it->glyph_row->glyphs[area + 1])
1610 {
1611 glyph->charpos = CHARPOS (it->position);
1612 glyph->object = it->object;
1613 glyph->pixel_width = it->pixel_width;
1614 glyph->voffset = it->voffset;
1615 glyph->type = CHAR_GLYPH;
1616 glyph->multibyte_p = it->multibyte_p;
1617 glyph->left_box_line_p = it->start_of_box_run_p;
1618 glyph->right_box_line_p = it->end_of_box_run_p;
1619 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1620 || it->phys_descent > it->descent);
1621 glyph->padding_p = 0;
1622 glyph->glyph_not_available_p = it->glyph_not_available_p;
1623 glyph->face_id = it->face_id;
1624 glyph->u.ch = it->char_to_display;
1625 glyph->w32_font_type = UNKNOWN_FONT;
1626 ++it->glyph_row->used[area];
1627 }
1628 }
1629
1630 /* Store one glyph for the composition IT->cmp_id in IT->glyph_row.
1631 Called from x_produce_glyphs when IT->glyph_row is non-null. */
1632
1633 static INLINE void
1634 x_append_composite_glyph (it)
1635 struct it *it;
1636 {
1637 struct glyph *glyph;
1638 enum glyph_row_area area = it->area;
1639
1640 xassert (it->glyph_row);
1641
1642 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1643 if (glyph < it->glyph_row->glyphs[area + 1])
1644 {
1645 glyph->charpos = CHARPOS (it->position);
1646 glyph->object = it->object;
1647 glyph->pixel_width = it->pixel_width;
1648 glyph->voffset = it->voffset;
1649 glyph->type = COMPOSITE_GLYPH;
1650 glyph->multibyte_p = it->multibyte_p;
1651 glyph->left_box_line_p = it->start_of_box_run_p;
1652 glyph->right_box_line_p = it->end_of_box_run_p;
1653 glyph->overlaps_vertically_p = (it->phys_ascent > it->ascent
1654 || it->phys_descent > it->descent);
1655 glyph->padding_p = 0;
1656 glyph->glyph_not_available_p = 0;
1657 glyph->face_id = it->face_id;
1658 glyph->u.cmp_id = it->cmp_id;
1659 glyph->w32_font_type = UNKNOWN_FONT;
1660 ++it->glyph_row->used[area];
1661 }
1662 }
1663
1664
1665 /* Change IT->ascent and IT->height according to the setting of
1666 IT->voffset. */
1667
1668 static INLINE void
1669 take_vertical_position_into_account (it)
1670 struct it *it;
1671 {
1672 if (it->voffset)
1673 {
1674 if (it->voffset < 0)
1675 /* Increase the ascent so that we can display the text higher
1676 in the line. */
1677 it->ascent += abs (it->voffset);
1678 else
1679 /* Increase the descent so that we can display the text lower
1680 in the line. */
1681 it->descent += it->voffset;
1682 }
1683 }
1684
1685
1686 /* Produce glyphs/get display metrics for the image IT is loaded with.
1687 See the description of struct display_iterator in dispextern.h for
1688 an overview of struct display_iterator. */
1689
1690 static void
1691 x_produce_image_glyph (it)
1692 struct it *it;
1693 {
1694 struct image *img;
1695 struct face *face;
1696
1697 xassert (it->what == IT_IMAGE);
1698
1699 face = FACE_FROM_ID (it->f, it->face_id);
1700 img = IMAGE_FROM_ID (it->f, it->image_id);
1701 xassert (img);
1702
1703 /* Make sure X resources of the face and image are loaded. */
1704 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1705 prepare_image_for_display (it->f, img);
1706
1707 it->ascent = it->phys_ascent = image_ascent (img, face);
1708 it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent;
1709 it->pixel_width = img->width + 2 * img->hmargin;
1710
1711 it->nglyphs = 1;
1712
1713 if (face->box != FACE_NO_BOX)
1714 {
1715 if (face->box_line_width > 0)
1716 {
1717 it->ascent += face->box_line_width;
1718 it->descent += face->box_line_width;
1719 }
1720
1721 if (it->start_of_box_run_p)
1722 it->pixel_width += abs (face->box_line_width);
1723 if (it->end_of_box_run_p)
1724 it->pixel_width += abs (face->box_line_width);
1725 }
1726
1727 take_vertical_position_into_account (it);
1728
1729 if (it->glyph_row)
1730 {
1731 struct glyph *glyph;
1732 enum glyph_row_area area = it->area;
1733
1734 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1735 if (glyph < it->glyph_row->glyphs[area + 1])
1736 {
1737 glyph->charpos = CHARPOS (it->position);
1738 glyph->object = it->object;
1739 glyph->pixel_width = it->pixel_width;
1740 glyph->voffset = it->voffset;
1741 glyph->type = IMAGE_GLYPH;
1742 glyph->multibyte_p = it->multibyte_p;
1743 glyph->left_box_line_p = it->start_of_box_run_p;
1744 glyph->right_box_line_p = it->end_of_box_run_p;
1745 glyph->overlaps_vertically_p = 0;
1746 glyph->padding_p = 0;
1747 glyph->glyph_not_available_p = 0;
1748 glyph->face_id = it->face_id;
1749 glyph->u.img_id = img->id;
1750 glyph->w32_font_type = UNKNOWN_FONT;
1751 ++it->glyph_row->used[area];
1752 }
1753 }
1754 }
1755
1756
1757 /* Append a stretch glyph to IT->glyph_row. OBJECT is the source
1758 of the glyph, WIDTH and HEIGHT are the width and height of the
1759 stretch. ASCENT is the percentage/100 of HEIGHT to use for the
1760 ascent of the glyph (0 <= ASCENT <= 1). */
1761
1762 static void
1763 x_append_stretch_glyph (it, object, width, height, ascent)
1764 struct it *it;
1765 Lisp_Object object;
1766 int width, height;
1767 double ascent;
1768 {
1769 struct glyph *glyph;
1770 enum glyph_row_area area = it->area;
1771
1772 xassert (ascent >= 0 && ascent <= 1);
1773
1774 glyph = it->glyph_row->glyphs[area] + it->glyph_row->used[area];
1775 if (glyph < it->glyph_row->glyphs[area + 1])
1776 {
1777 glyph->charpos = CHARPOS (it->position);
1778 glyph->object = object;
1779 glyph->pixel_width = width;
1780 glyph->voffset = it->voffset;
1781 glyph->type = STRETCH_GLYPH;
1782 glyph->multibyte_p = it->multibyte_p;
1783 glyph->left_box_line_p = it->start_of_box_run_p;
1784 glyph->right_box_line_p = it->end_of_box_run_p;
1785 glyph->overlaps_vertically_p = 0;
1786 glyph->padding_p = 0;
1787 glyph->glyph_not_available_p = 0;
1788 glyph->face_id = it->face_id;
1789 glyph->u.stretch.ascent = height * ascent;
1790 glyph->u.stretch.height = height;
1791 glyph->w32_font_type = UNKNOWN_FONT;
1792 ++it->glyph_row->used[area];
1793 }
1794 }
1795
1796
1797 /* Produce a stretch glyph for iterator IT. IT->object is the value
1798 of the glyph property displayed. The value must be a list
1799 `(space KEYWORD VALUE ...)' with the following KEYWORD/VALUE pairs
1800 being recognized:
1801
1802 1. `:width WIDTH' specifies that the space should be WIDTH *
1803 canonical char width wide. WIDTH may be an integer or floating
1804 point number.
1805
1806 2. `:relative-width FACTOR' specifies that the width of the stretch
1807 should be computed from the width of the first character having the
1808 `glyph' property, and should be FACTOR times that width.
1809
1810 3. `:align-to HPOS' specifies that the space should be wide enough
1811 to reach HPOS, a value in canonical character units.
1812
1813 Exactly one of the above pairs must be present.
1814
1815 4. `:height HEIGHT' specifies that the height of the stretch produced
1816 should be HEIGHT, measured in canonical character units.
1817
1818 5. `:relative-height FACTOR' specifies that the height of the
1819 stretch should be FACTOR times the height of the characters having
1820 the glyph property.
1821
1822 Either none or exactly one of 4 or 5 must be present.
1823
1824 6. `:ascent ASCENT' specifies that ASCENT percent of the height
1825 of the stretch should be used for the ascent of the stretch.
1826 ASCENT must be in the range 0 <= ASCENT <= 100. */
1827
1828 #define NUMVAL(X) \
1829 ((INTEGERP (X) || FLOATP (X)) \
1830 ? XFLOATINT (X) \
1831 : - 1)
1832
1833
1834 static void
1835 x_produce_stretch_glyph (it)
1836 struct it *it;
1837 {
1838 /* (space :width WIDTH :height HEIGHT. */
1839 #if GLYPH_DEBUG
1840 extern Lisp_Object Qspace;
1841 #endif
1842 extern Lisp_Object QCwidth, QCheight, QCascent;
1843 extern Lisp_Object QCrelative_width, QCrelative_height;
1844 extern Lisp_Object QCalign_to;
1845 Lisp_Object prop, plist;
1846 double width = 0, height = 0, ascent = 0;
1847 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1848 XFontStruct *font = face->font ? face->font : FRAME_FONT (it->f);
1849
1850 PREPARE_FACE_FOR_DISPLAY (it->f, face);
1851
1852 /* List should start with `space'. */
1853 xassert (CONSP (it->object) && EQ (XCAR (it->object), Qspace));
1854 plist = XCDR (it->object);
1855
1856 /* Compute the width of the stretch. */
1857 if (prop = Fplist_get (plist, QCwidth),
1858 NUMVAL (prop) > 0)
1859 /* Absolute width `:width WIDTH' specified and valid. */
1860 width = NUMVAL (prop) * CANON_X_UNIT (it->f);
1861 else if (prop = Fplist_get (plist, QCrelative_width),
1862 NUMVAL (prop) > 0)
1863 {
1864 /* Relative width `:relative-width FACTOR' specified and valid.
1865 Compute the width of the characters having the `glyph'
1866 property. */
1867 struct it it2;
1868 unsigned char *p = BYTE_POS_ADDR (IT_BYTEPOS (*it));
1869
1870 it2 = *it;
1871 if (it->multibyte_p)
1872 {
1873 int maxlen = ((IT_BYTEPOS (*it) >= GPT ? ZV : GPT)
1874 - IT_BYTEPOS (*it));
1875 it2.c = STRING_CHAR_AND_LENGTH (p, maxlen, it2.len);
1876 }
1877 else
1878 it2.c = *p, it2.len = 1;
1879
1880 it2.glyph_row = NULL;
1881 it2.what = IT_CHARACTER;
1882 x_produce_glyphs (&it2);
1883 width = NUMVAL (prop) * it2.pixel_width;
1884 }
1885 else if (prop = Fplist_get (plist, QCalign_to),
1886 NUMVAL (prop) > 0)
1887 width = NUMVAL (prop) * CANON_X_UNIT (it->f) - it->current_x;
1888 else
1889 /* Nothing specified -> width defaults to canonical char width. */
1890 width = CANON_X_UNIT (it->f);
1891
1892 /* Compute height. */
1893 if (prop = Fplist_get (plist, QCheight),
1894 NUMVAL (prop) > 0)
1895 height = NUMVAL (prop) * CANON_Y_UNIT (it->f);
1896 else if (prop = Fplist_get (plist, QCrelative_height),
1897 NUMVAL (prop) > 0)
1898 height = FONT_HEIGHT (font) * NUMVAL (prop);
1899 else
1900 height = FONT_HEIGHT (font);
1901
1902 /* Compute percentage of height used for ascent. If
1903 `:ascent ASCENT' is present and valid, use that. Otherwise,
1904 derive the ascent from the font in use. */
1905 if (prop = Fplist_get (plist, QCascent),
1906 NUMVAL (prop) > 0 && NUMVAL (prop) <= 100)
1907 ascent = NUMVAL (prop) / 100.0;
1908 else
1909 ascent = (double) FONT_BASE (font) / FONT_HEIGHT (font);
1910
1911 if (width <= 0)
1912 width = 1;
1913 if (height <= 0)
1914 height = 1;
1915
1916 if (it->glyph_row)
1917 {
1918 Lisp_Object object = it->stack[it->sp - 1].string;
1919 if (!STRINGP (object))
1920 object = it->w->buffer;
1921 x_append_stretch_glyph (it, object, width, height, ascent);
1922 }
1923
1924 it->pixel_width = width;
1925 it->ascent = it->phys_ascent = height * ascent;
1926 it->descent = it->phys_descent = height - it->ascent;
1927 it->nglyphs = 1;
1928
1929 if (face->box != FACE_NO_BOX)
1930 {
1931 if (face->box_line_width > 0)
1932 {
1933 it->ascent += face->box_line_width;
1934 it->descent += face->box_line_width;
1935 }
1936
1937 if (it->start_of_box_run_p)
1938 it->pixel_width += abs (face->box_line_width);
1939 if (it->end_of_box_run_p)
1940 it->pixel_width += abs (face->box_line_width);
1941 }
1942
1943 take_vertical_position_into_account (it);
1944 }
1945
1946 /* Return proper value to be used as baseline offset of font that has
1947 ASCENT and DESCENT to draw characters by the font at the vertical
1948 center of the line of frame F.
1949
1950 Here, out task is to find the value of BOFF in the following figure;
1951
1952 -------------------------+-----------+-
1953 -+-+---------+-+ | |
1954 | | | | | |
1955 | | | | F_ASCENT F_HEIGHT
1956 | | | ASCENT | |
1957 HEIGHT | | | | |
1958 | | |-|-+------+-----------|------- baseline
1959 | | | | BOFF | |
1960 | |---------|-+-+ | |
1961 | | | DESCENT | |
1962 -+-+---------+-+ F_DESCENT |
1963 -------------------------+-----------+-
1964
1965 -BOFF + DESCENT + (F_HEIGHT - HEIGHT) / 2 = F_DESCENT
1966 BOFF = DESCENT + (F_HEIGHT - HEIGHT) / 2 - F_DESCENT
1967 DESCENT = FONT->descent
1968 HEIGHT = FONT_HEIGHT (FONT)
1969 F_DESCENT = (F->output_data.x->font->descent
1970 - F->output_data.x->baseline_offset)
1971 F_HEIGHT = FRAME_LINE_HEIGHT (F)
1972 */
1973
1974 #define VCENTER_BASELINE_OFFSET(FONT, F) \
1975 (FONT_DESCENT (FONT) \
1976 + (FRAME_LINE_HEIGHT ((F)) - FONT_HEIGHT ((FONT)) \
1977 + (FRAME_LINE_HEIGHT ((F)) > FONT_HEIGHT ((FONT)))) / 2 \
1978 - (FONT_DESCENT (FRAME_FONT (F)) - FRAME_BASELINE_OFFSET (F)))
1979
1980 /* Produce glyphs/get display metrics for the display element IT is
1981 loaded with. See the description of struct display_iterator in
1982 dispextern.h for an overview of struct display_iterator. */
1983
1984 static void
1985 x_produce_glyphs (it)
1986 struct it *it;
1987 {
1988 it->glyph_not_available_p = 0;
1989
1990 if (it->what == IT_CHARACTER)
1991 {
1992 wchar_t char2b;
1993 XFontStruct *font;
1994 struct face *face = FACE_FROM_ID (it->f, it->face_id);
1995 XCharStruct *pcm;
1996 int font_not_found_p;
1997 struct font_info *font_info;
1998 int boff; /* baseline offset */
1999 /* We may change it->multibyte_p upon unibyte<->multibyte
2000 conversion. So, save the current value now and restore it
2001 later.
2002
2003 Note: It seems that we don't have to record multibyte_p in
2004 struct glyph because the character code itself tells if or
2005 not the character is multibyte. Thus, in the future, we must
2006 consider eliminating the field `multibyte_p' in the struct
2007 glyph.
2008 */
2009 int saved_multibyte_p = it->multibyte_p;
2010
2011 /* Maybe translate single-byte characters to multibyte, or the
2012 other way. */
2013 it->char_to_display = it->c;
2014 if (!ASCII_BYTE_P (it->c))
2015 {
2016 if (unibyte_display_via_language_environment
2017 && SINGLE_BYTE_CHAR_P (it->c)
2018 && (it->c >= 0240
2019 || !NILP (Vnonascii_translation_table)))
2020 {
2021 it->char_to_display = unibyte_char_to_multibyte (it->c);
2022 it->multibyte_p = 1;
2023 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2024 face = FACE_FROM_ID (it->f, it->face_id);
2025 }
2026 else if (!SINGLE_BYTE_CHAR_P (it->c)
2027 && !it->multibyte_p)
2028 {
2029 it->multibyte_p = 1;
2030 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2031 face = FACE_FROM_ID (it->f, it->face_id);
2032 }
2033 }
2034
2035 /* Get font to use. Encode IT->char_to_display. */
2036 x_get_char_face_and_encoding (it->f, it->char_to_display,
2037 it->face_id, &char2b,
2038 it->multibyte_p);
2039 font = face->font;
2040
2041 /* When no suitable font found, use the default font. */
2042 font_not_found_p = font == NULL;
2043 if (font_not_found_p)
2044 {
2045 font = FRAME_FONT (it->f);
2046 boff = it->f->output_data.w32->baseline_offset;
2047 font_info = NULL;
2048 }
2049 else
2050 {
2051 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2052 boff = font_info->baseline_offset;
2053 if (font_info->vertical_centering)
2054 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2055 }
2056
2057 if (it->char_to_display >= ' '
2058 && (!it->multibyte_p || it->char_to_display < 128))
2059 {
2060 /* Either unibyte or ASCII. */
2061 int stretched_p;
2062
2063 it->nglyphs = 1;
2064
2065 pcm = w32_per_char_metric (font, &char2b,
2066 font->bdf ? BDF_1D_FONT : ANSI_FONT);
2067 it->ascent = FONT_BASE (font) + boff;
2068 it->descent = FONT_DESCENT (font) - boff;
2069
2070 if (pcm)
2071 {
2072 it->phys_ascent = pcm->ascent + boff;
2073 it->phys_descent = pcm->descent - boff;
2074 it->pixel_width = pcm->width;
2075 }
2076 else
2077 {
2078 it->glyph_not_available_p = 1;
2079 it->phys_ascent = FONT_BASE (font) + boff;
2080 it->phys_descent = FONT_DESCENT (font) - boff;
2081 it->pixel_width = FONT_WIDTH (font);
2082 }
2083
2084 /* If this is a space inside a region of text with
2085 `space-width' property, change its width. */
2086 stretched_p = it->char_to_display == ' ' && !NILP (it->space_width);
2087 if (stretched_p)
2088 it->pixel_width *= XFLOATINT (it->space_width);
2089
2090 /* If face has a box, add the box thickness to the character
2091 height. If character has a box line to the left and/or
2092 right, add the box line width to the character's width. */
2093 if (face->box != FACE_NO_BOX)
2094 {
2095 int thick = face->box_line_width;
2096
2097 if (thick > 0)
2098 {
2099 it->ascent += thick;
2100 it->descent += thick;
2101 }
2102 else
2103 thick = -thick;
2104
2105 if (it->start_of_box_run_p)
2106 it->pixel_width += thick;
2107 if (it->end_of_box_run_p)
2108 it->pixel_width += thick;
2109 }
2110
2111 /* If face has an overline, add the height of the overline
2112 (1 pixel) and a 1 pixel margin to the character height. */
2113 if (face->overline_p)
2114 it->ascent += 2;
2115
2116 take_vertical_position_into_account (it);
2117
2118 /* If we have to actually produce glyphs, do it. */
2119 if (it->glyph_row)
2120 {
2121 if (stretched_p)
2122 {
2123 /* Translate a space with a `space-width' property
2124 into a stretch glyph. */
2125 double ascent = (double) FONT_BASE (font)
2126 / FONT_HEIGHT (font);
2127 x_append_stretch_glyph (it, it->object, it->pixel_width,
2128 it->ascent + it->descent, ascent);
2129 }
2130 else
2131 x_append_glyph (it);
2132
2133 /* If characters with lbearing or rbearing are displayed
2134 in this line, record that fact in a flag of the
2135 glyph row. This is used to optimize X output code. */
2136 if (pcm && (pcm->lbearing < 0 || pcm->rbearing > pcm->width))
2137 it->glyph_row->contains_overlapping_glyphs_p = 1;
2138 }
2139 }
2140 else if (it->char_to_display == '\n')
2141 {
2142 /* A newline has no width but we need the height of the line. */
2143 it->pixel_width = 0;
2144 it->nglyphs = 0;
2145 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2146 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2147
2148 if (face->box != FACE_NO_BOX
2149 && face->box_line_width > 0)
2150 {
2151 it->ascent += face->box_line_width;
2152 it->descent += face->box_line_width;
2153 }
2154 }
2155 else if (it->char_to_display == '\t')
2156 {
2157 int tab_width = it->tab_width * CANON_X_UNIT (it->f);
2158 int x = it->current_x + it->continuation_lines_width;
2159 int next_tab_x = ((1 + x + tab_width - 1) / tab_width) * tab_width;
2160
2161 /* If the distance from the current position to the next tab
2162 stop is less than a canonical character width, use the
2163 tab stop after that. */
2164 if (next_tab_x - x < CANON_X_UNIT (it->f))
2165 next_tab_x += tab_width;
2166
2167 it->pixel_width = next_tab_x - x;
2168 it->nglyphs = 1;
2169 it->ascent = it->phys_ascent = FONT_BASE (font) + boff;
2170 it->descent = it->phys_descent = FONT_DESCENT (font) - boff;
2171
2172 if (it->glyph_row)
2173 {
2174 double ascent = (double) it->ascent / (it->ascent + it->descent);
2175 x_append_stretch_glyph (it, it->object, it->pixel_width,
2176 it->ascent + it->descent, ascent);
2177 }
2178 }
2179 else
2180 {
2181 /* A multi-byte character.
2182 If we found a font, this font should give us the right
2183 metrics. If we didn't find a font, use the frame's
2184 default font and calculate the width of the character
2185 from the charset width; this is what old redisplay code
2186 did. */
2187 enum w32_char_font_type type;
2188
2189 if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
2190 type = BDF_1D_FONT;
2191 else if (font->bdf)
2192 type = BDF_2D_FONT;
2193 else
2194 type = UNICODE_FONT;
2195
2196 pcm = w32_per_char_metric (font, &char2b, type);
2197
2198 if (font_not_found_p || !pcm)
2199 {
2200 int charset = CHAR_CHARSET (it->char_to_display);
2201
2202 it->glyph_not_available_p = 1;
2203 it->pixel_width = (FONT_WIDTH (FRAME_FONT (it->f))
2204 * CHARSET_WIDTH (charset));
2205 it->phys_ascent = FONT_BASE (font) + boff;
2206 it->phys_descent = FONT_DESCENT (font) - boff;
2207 }
2208 else
2209 {
2210 it->pixel_width = pcm->width;
2211 it->phys_ascent = pcm->ascent + boff;
2212 it->phys_descent = pcm->descent - boff;
2213 if (it->glyph_row
2214 && (pcm->lbearing < 0
2215 || pcm->rbearing > pcm->width))
2216 it->glyph_row->contains_overlapping_glyphs_p = 1;
2217 }
2218 it->nglyphs = 1;
2219 it->ascent = FONT_BASE (font) + boff;
2220 it->descent = FONT_DESCENT (font) - boff;
2221 if (face->box != FACE_NO_BOX)
2222 {
2223 int thick = face->box_line_width;
2224
2225 if (thick > 0)
2226 {
2227 it->ascent += thick;
2228 it->descent += thick;
2229 }
2230 else
2231 thick = - thick;
2232
2233 if (it->start_of_box_run_p)
2234 it->pixel_width += thick;
2235 if (it->end_of_box_run_p)
2236 it->pixel_width += thick;
2237 }
2238
2239 /* If face has an overline, add the height of the overline
2240 (1 pixel) and a 1 pixel margin to the character height. */
2241 if (face->overline_p)
2242 it->ascent += 2;
2243
2244 take_vertical_position_into_account (it);
2245
2246 if (it->glyph_row)
2247 x_append_glyph (it);
2248 }
2249 it->multibyte_p = saved_multibyte_p;
2250 }
2251 else if (it->what == IT_COMPOSITION)
2252 {
2253 /* Note: A composition is represented as one glyph in the
2254 glyph matrix. There are no padding glyphs. */
2255 wchar_t char2b;
2256 XFontStruct *font;
2257 struct face *face = FACE_FROM_ID (it->f, it->face_id);
2258 XCharStruct *pcm;
2259 int font_not_found_p;
2260 struct font_info *font_info;
2261 int boff; /* baseline offset */
2262 struct composition *cmp = composition_table[it->cmp_id];
2263
2264 /* Maybe translate single-byte characters to multibyte. */
2265 it->char_to_display = it->c;
2266 if (unibyte_display_via_language_environment
2267 && SINGLE_BYTE_CHAR_P (it->c)
2268 && (it->c >= 0240
2269 || (it->c >= 0200
2270 && !NILP (Vnonascii_translation_table))))
2271 {
2272 it->char_to_display = unibyte_char_to_multibyte (it->c);
2273 }
2274
2275 /* Get face and font to use. Encode IT->char_to_display. */
2276 it->face_id = FACE_FOR_CHAR (it->f, face, it->char_to_display);
2277 face = FACE_FROM_ID (it->f, it->face_id);
2278 x_get_char_face_and_encoding (it->f, it->char_to_display,
2279 it->face_id, &char2b, it->multibyte_p);
2280 font = face->font;
2281
2282 /* When no suitable font found, use the default font. */
2283 font_not_found_p = font == NULL;
2284 if (font_not_found_p)
2285 {
2286 font = FRAME_FONT (it->f);
2287 boff = it->f->output_data.w32->baseline_offset;
2288 font_info = NULL;
2289 }
2290 else
2291 {
2292 font_info = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2293 boff = font_info->baseline_offset;
2294 if (font_info->vertical_centering)
2295 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2296 }
2297
2298 /* There are no padding glyphs, so there is only one glyph to
2299 produce for the composition. Important is that pixel_width,
2300 ascent and descent are the values of what is drawn by
2301 draw_glyphs (i.e. the values of the overall glyphs composed). */
2302 it->nglyphs = 1;
2303
2304 /* If we have not yet calculated pixel size data of glyphs of
2305 the composition for the current face font, calculate them
2306 now. Theoretically, we have to check all fonts for the
2307 glyphs, but that requires much time and memory space. So,
2308 here we check only the font of the first glyph. This leads
2309 to incorrect display very rarely, and C-l (recenter) can
2310 correct the display anyway. */
2311 if (cmp->font != (void *) font)
2312 {
2313 /* Ascent and descent of the font of the first character of
2314 this composition (adjusted by baseline offset). Ascent
2315 and descent of overall glyphs should not be less than
2316 them respectively. */
2317 int font_ascent = FONT_BASE (font) + boff;
2318 int font_descent = FONT_DESCENT (font) - boff;
2319 /* Bounding box of the overall glyphs. */
2320 int leftmost, rightmost, lowest, highest;
2321 int i, width, ascent, descent;
2322 enum w32_char_font_type font_type;
2323
2324 cmp->font = (void *) font;
2325
2326 if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (it->c)) == 1)
2327 font_type = BDF_1D_FONT;
2328 else if (font->bdf)
2329 font_type = BDF_2D_FONT;
2330 else
2331 font_type = UNICODE_FONT;
2332
2333 /* Initialize the bounding box. */
2334 if (font_info
2335 && (pcm = w32_per_char_metric (font, &char2b, font_type)))
2336 {
2337 width = pcm->width;
2338 ascent = pcm->ascent;
2339 descent = pcm->descent;
2340 }
2341 else
2342 {
2343 width = FONT_WIDTH (font);
2344 ascent = FONT_BASE (font);
2345 descent = FONT_DESCENT (font);
2346 }
2347
2348 rightmost = width;
2349 lowest = - descent + boff;
2350 highest = ascent + boff;
2351 leftmost = 0;
2352
2353 if (font_info
2354 && font_info->default_ascent
2355 && CHAR_TABLE_P (Vuse_default_ascent)
2356 && !NILP (Faref (Vuse_default_ascent,
2357 make_number (it->char_to_display))))
2358 highest = font_info->default_ascent + boff;
2359
2360 /* Draw the first glyph at the normal position. It may be
2361 shifted to right later if some other glyphs are drawn at
2362 the left. */
2363 cmp->offsets[0] = 0;
2364 cmp->offsets[1] = boff;
2365
2366 /* Set cmp->offsets for the remaining glyphs. */
2367 for (i = 1; i < cmp->glyph_len; i++)
2368 {
2369 int left, right, btm, top;
2370 int ch = COMPOSITION_GLYPH (cmp, i);
2371 int face_id = FACE_FOR_CHAR (it->f, face, ch);
2372
2373 face = FACE_FROM_ID (it->f, face_id);
2374 x_get_char_face_and_encoding (it->f, ch, face->id, &char2b,
2375 it->multibyte_p);
2376 font = face->font;
2377 if (font == NULL)
2378 {
2379 font = FRAME_FONT (it->f);
2380 boff = it->f->output_data.w32->baseline_offset;
2381 font_info = NULL;
2382 }
2383 else
2384 {
2385 font_info
2386 = FONT_INFO_FROM_ID (it->f, face->font_info_id);
2387 boff = font_info->baseline_offset;
2388 if (font_info->vertical_centering)
2389 boff = VCENTER_BASELINE_OFFSET (font, it->f) - boff;
2390 }
2391
2392 if (font->bdf && CHARSET_DIMENSION (CHAR_CHARSET (ch)) == 1)
2393 font_type = BDF_1D_FONT;
2394 else if (font->bdf)
2395 font_type = BDF_2D_FONT;
2396 else
2397 font_type = UNICODE_FONT;
2398
2399 if (font_info
2400 && (pcm = w32_per_char_metric (font, &char2b, font_type)))
2401 {
2402 width = pcm->width;
2403 ascent = pcm->ascent;
2404 descent = pcm->descent;
2405 }
2406 else
2407 {
2408 width = FONT_WIDTH (font);
2409 ascent = 1;
2410 descent = 0;
2411 }
2412
2413 if (cmp->method != COMPOSITION_WITH_RULE_ALTCHARS)
2414 {
2415 /* Relative composition with or without
2416 alternate chars. */
2417 left = (leftmost + rightmost - width) / 2;
2418 btm = - descent + boff;
2419 if (font_info && font_info->relative_compose
2420 && (! CHAR_TABLE_P (Vignore_relative_composition)
2421 || NILP (Faref (Vignore_relative_composition,
2422 make_number (ch)))))
2423 {
2424
2425 if (- descent >= font_info->relative_compose)
2426 /* One extra pixel between two glyphs. */
2427 btm = highest + 1;
2428 else if (ascent <= 0)
2429 /* One extra pixel between two glyphs. */
2430 btm = lowest - 1 - ascent - descent;
2431 }
2432 }
2433 else
2434 {
2435 /* A composition rule is specified by an integer
2436 value that encodes global and new reference
2437 points (GREF and NREF). GREF and NREF are
2438 specified by numbers as below:
2439
2440 0---1---2 -- ascent
2441 | |
2442 | |
2443 | |
2444 9--10--11 -- center
2445 | |
2446 ---3---4---5--- baseline
2447 | |
2448 6---7---8 -- descent
2449 */
2450 int rule = COMPOSITION_RULE (cmp, i);
2451 int gref, nref, grefx, grefy, nrefx, nrefy;
2452
2453 COMPOSITION_DECODE_RULE (rule, gref, nref);
2454 grefx = gref % 3, nrefx = nref % 3;
2455 grefy = gref / 3, nrefy = nref / 3;
2456
2457 left = (leftmost
2458 + grefx * (rightmost - leftmost) / 2
2459 - nrefx * width / 2);
2460 btm = ((grefy == 0 ? highest
2461 : grefy == 1 ? 0
2462 : grefy == 2 ? lowest
2463 : (highest + lowest) / 2)
2464 - (nrefy == 0 ? ascent + descent
2465 : nrefy == 1 ? descent - boff
2466 : nrefy == 2 ? 0
2467 : (ascent + descent) / 2));
2468 }
2469
2470 cmp->offsets[i * 2] = left;
2471 cmp->offsets[i * 2 + 1] = btm + descent;
2472
2473 /* Update the bounding box of the overall glyphs. */
2474 right = left + width;
2475 top = btm + descent + ascent;
2476 if (left < leftmost)
2477 leftmost = left;
2478 if (right > rightmost)
2479 rightmost = right;
2480 if (top > highest)
2481 highest = top;
2482 if (btm < lowest)
2483 lowest = btm;
2484 }
2485
2486 /* If there are glyphs whose x-offsets are negative,
2487 shift all glyphs to the right and make all x-offsets
2488 non-negative. */
2489 if (leftmost < 0)
2490 {
2491 for (i = 0; i < cmp->glyph_len; i++)
2492 cmp->offsets[i * 2] -= leftmost;
2493 rightmost -= leftmost;
2494 }
2495
2496 cmp->pixel_width = rightmost;
2497 cmp->ascent = highest;
2498 cmp->descent = - lowest;
2499 if (cmp->ascent < font_ascent)
2500 cmp->ascent = font_ascent;
2501 if (cmp->descent < font_descent)
2502 cmp->descent = font_descent;
2503 }
2504
2505 it->pixel_width = cmp->pixel_width;
2506 it->ascent = it->phys_ascent = cmp->ascent;
2507 it->descent = it->phys_descent = cmp->descent;
2508
2509 if (face->box != FACE_NO_BOX)
2510 {
2511 int thick = face->box_line_width;
2512
2513 if (thick > 0)
2514 {
2515 it->ascent += thick;
2516 it->descent += thick;
2517 }
2518 else
2519 thick = - thick;
2520
2521 if (it->start_of_box_run_p)
2522 it->pixel_width += thick;
2523 if (it->end_of_box_run_p)
2524 it->pixel_width += thick;
2525 }
2526
2527 /* If face has an overline, add the height of the overline
2528 (1 pixel) and a 1 pixel margin to the character height. */
2529 if (face->overline_p)
2530 it->ascent += 2;
2531
2532 take_vertical_position_into_account (it);
2533
2534 if (it->glyph_row)
2535 x_append_composite_glyph (it);
2536 }
2537 else if (it->what == IT_IMAGE)
2538 x_produce_image_glyph (it);
2539 else if (it->what == IT_STRETCH)
2540 x_produce_stretch_glyph (it);
2541
2542 /* Accumulate dimensions. Note: can't assume that it->descent > 0
2543 because this isn't true for images with `:ascent 100'. */
2544 xassert (it->ascent >= 0 && it->descent >= 0);
2545 if (it->area == TEXT_AREA)
2546 it->current_x += it->pixel_width;
2547
2548 it->descent += it->extra_line_spacing;
2549
2550 it->max_ascent = max (it->max_ascent, it->ascent);
2551 it->max_descent = max (it->max_descent, it->descent);
2552 it->max_phys_ascent = max (it->max_phys_ascent, it->phys_ascent);
2553 it->max_phys_descent = max (it->max_phys_descent, it->phys_descent);
2554 }
2555
2556
2557 /* Estimate the pixel height of the mode or top line on frame F.
2558 FACE_ID specifies what line's height to estimate. */
2559
2560 int
2561 x_estimate_mode_line_height (f, face_id)
2562 struct frame *f;
2563 enum face_id face_id;
2564 {
2565 int height = FONT_HEIGHT (FRAME_FONT (f));
2566
2567 /* This function is called so early when Emacs starts that the face
2568 cache and mode line face are not yet initialized. */
2569 if (FRAME_FACE_CACHE (f))
2570 {
2571 struct face *face = FACE_FROM_ID (f, face_id);
2572 if (face)
2573 {
2574 if (face->font)
2575 height = FONT_HEIGHT (face->font);
2576 if (face->box_line_width > 0)
2577 height += 2 * face->box_line_width;
2578 }
2579 }
2580
2581 return height;
2582 }
2583
2584 \f
2585 /***********************************************************************
2586 Glyph display
2587 ***********************************************************************/
2588
2589 /* A sequence of glyphs to be drawn in the same face.
2590
2591 This data structure is not really completely X specific, so it
2592 could possibly, at least partially, be useful for other systems. It
2593 is currently not part of the external redisplay interface because
2594 it's not clear what other systems will need. */
2595
2596 struct glyph_string
2597 {
2598 /* X-origin of the string. */
2599 int x;
2600
2601 /* Y-origin and y-position of the base line of this string. */
2602 int y, ybase;
2603
2604 /* The width of the string, not including a face extension. */
2605 int width;
2606
2607 /* The width of the string, including a face extension. */
2608 int background_width;
2609
2610 /* The height of this string. This is the height of the line this
2611 string is drawn in, and can be different from the height of the
2612 font the string is drawn in. */
2613 int height;
2614
2615 /* Number of pixels this string overwrites in front of its x-origin.
2616 This number is zero if the string has an lbearing >= 0; it is
2617 -lbearing, if the string has an lbearing < 0. */
2618 int left_overhang;
2619
2620 /* Number of pixels this string overwrites past its right-most
2621 nominal x-position, i.e. x + width. Zero if the string's
2622 rbearing is <= its nominal width, rbearing - width otherwise. */
2623 int right_overhang;
2624
2625 /* The frame on which the glyph string is drawn. */
2626 struct frame *f;
2627
2628 /* The window on which the glyph string is drawn. */
2629 struct window *w;
2630
2631 /* X display and window for convenience. */
2632 Window window;
2633
2634 /* The glyph row for which this string was built. It determines the
2635 y-origin and height of the string. */
2636 struct glyph_row *row;
2637
2638 /* The area within row. */
2639 enum glyph_row_area area;
2640
2641 /* Characters to be drawn, and number of characters. */
2642 wchar_t *char2b;
2643 int nchars;
2644
2645 /* A face-override for drawing cursors, mouse face and similar. */
2646 enum draw_glyphs_face hl;
2647
2648 /* Face in which this string is to be drawn. */
2649 struct face *face;
2650
2651 /* Font in which this string is to be drawn. */
2652 XFontStruct *font;
2653
2654 /* Font info for this string. */
2655 struct font_info *font_info;
2656
2657 /* Non-null means this string describes (part of) a composition.
2658 All characters from char2b are drawn composed. */
2659 struct composition *cmp;
2660
2661 /* Index of this glyph string's first character in the glyph
2662 definition of CMP. If this is zero, this glyph string describes
2663 the first character of a composition. */
2664 int gidx;
2665
2666 /* 1 means this glyph strings face has to be drawn to the right end
2667 of the window's drawing area. */
2668 unsigned extends_to_end_of_line_p : 1;
2669
2670 /* 1 means the background of this string has been drawn. */
2671 unsigned background_filled_p : 1;
2672
2673 /* 1 means glyph string must be drawn with 16-bit functions. */
2674 unsigned two_byte_p : 1;
2675
2676 /* 1 means that the original font determined for drawing this glyph
2677 string could not be loaded. The member `font' has been set to
2678 the frame's default font in this case. */
2679 unsigned font_not_found_p : 1;
2680
2681 /* 1 means that the face in which this glyph string is drawn has a
2682 stipple pattern. */
2683 unsigned stippled_p : 1;
2684
2685 /* 1 means only the foreground of this glyph string must be drawn,
2686 and we should use the physical height of the line this glyph
2687 string appears in as clip rect. */
2688 unsigned for_overlaps_p : 1;
2689
2690 /* The GC to use for drawing this glyph string. */
2691 XGCValues *gc;
2692
2693 HDC hdc;
2694
2695 /* A pointer to the first glyph in the string. This glyph
2696 corresponds to char2b[0]. Needed to draw rectangles if
2697 font_not_found_p is 1. */
2698 struct glyph *first_glyph;
2699
2700 /* Image, if any. */
2701 struct image *img;
2702
2703 struct glyph_string *next, *prev;
2704 };
2705
2706
2707 /* Encapsulate the different ways of displaying text under W32. */
2708
2709 void W32_TEXTOUT (s, x, y,chars,nchars)
2710 struct glyph_string * s;
2711 int x, y;
2712 wchar_t * chars;
2713 int nchars;
2714 {
2715 int charset_dim = w32_font_is_double_byte (s->gc->font) ? 2 : 1;
2716 if (s->gc->font->bdf)
2717 w32_BDF_TextOut (s->gc->font->bdf, s->hdc,
2718 x, y, (char *) chars, charset_dim,
2719 nchars * charset_dim, 0);
2720 else if (s->first_glyph->w32_font_type == UNICODE_FONT)
2721 ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
2722 else
2723 ExtTextOut (s->hdc, x, y, 0, NULL, (char *) chars,
2724 nchars * charset_dim, NULL);
2725 }
2726
2727 #if GLYPH_DEBUG
2728
2729 static void
2730 x_dump_glyph_string (s)
2731 struct glyph_string *s;
2732 {
2733 fprintf (stderr, "glyph string\n");
2734 fprintf (stderr, " x, y, w, h = %d, %d, %d, %d\n",
2735 s->x, s->y, s->width, s->height);
2736 fprintf (stderr, " ybase = %d\n", s->ybase);
2737 fprintf (stderr, " hl = %d\n", s->hl);
2738 fprintf (stderr, " left overhang = %d, right = %d\n",
2739 s->left_overhang, s->right_overhang);
2740 fprintf (stderr, " nchars = %d\n", s->nchars);
2741 fprintf (stderr, " extends to end of line = %d\n",
2742 s->extends_to_end_of_line_p);
2743 fprintf (stderr, " font height = %d\n", FONT_HEIGHT (s->font));
2744 fprintf (stderr, " bg width = %d\n", s->background_width);
2745 }
2746
2747 #endif /* GLYPH_DEBUG */
2748
2749
2750
2751 static void x_append_glyph_string_lists P_ ((struct glyph_string **,
2752 struct glyph_string **,
2753 struct glyph_string *,
2754 struct glyph_string *));
2755 static void x_prepend_glyph_string_lists P_ ((struct glyph_string **,
2756 struct glyph_string **,
2757 struct glyph_string *,
2758 struct glyph_string *));
2759 static void x_append_glyph_string P_ ((struct glyph_string **,
2760 struct glyph_string **,
2761 struct glyph_string *));
2762 static int x_left_overwritten P_ ((struct glyph_string *));
2763 static int x_left_overwriting P_ ((struct glyph_string *));
2764 static int x_right_overwritten P_ ((struct glyph_string *));
2765 static int x_right_overwriting P_ ((struct glyph_string *));
2766 static int x_fill_glyph_string P_ ((struct glyph_string *, int, int, int,
2767 int));
2768 static void w32_init_glyph_string P_ ((struct glyph_string *, HDC hdc,
2769 wchar_t *, struct window *,
2770 struct glyph_row *,
2771 enum glyph_row_area, int,
2772 enum draw_glyphs_face));
2773 static int x_draw_glyphs P_ ((struct window *, int , struct glyph_row *,
2774 enum glyph_row_area, int, int,
2775 enum draw_glyphs_face, int));
2776 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
2777 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
2778 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
2779 int));
2780 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
2781 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
2782 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
2783 static void x_draw_glyph_string P_ ((struct glyph_string *));
2784 static void x_compute_glyph_string_overhangs P_ ((struct glyph_string *));
2785 static void x_set_cursor_gc P_ ((struct glyph_string *));
2786 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
2787 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
2788 static void w32_get_glyph_overhangs P_ ((HDC hdc, struct glyph *,
2789 struct frame *,
2790 int *, int *));
2791 static void x_compute_overhangs_and_x P_ ((struct glyph_string *, int, int));
2792 static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
2793 static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
2794 double, int, COLORREF));
2795 static void x_setup_relief_colors P_ ((struct glyph_string *));
2796 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
2797 static void x_draw_image_relief P_ ((struct glyph_string *));
2798 static void x_draw_image_foreground P_ ((struct glyph_string *));
2799 static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
2800 static void x_fill_image_glyph_string P_ ((struct glyph_string *));
2801 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
2802 int, int, int));
2803 static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
2804 int, int, int, int, RECT *));
2805 static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
2806 int, int, int, RECT *));
2807 static void x_fix_overlapping_area P_ ((struct window *, struct glyph_row *,
2808 enum glyph_row_area));
2809 static int x_fill_stretch_glyph_string P_ ((struct glyph_string *,
2810 struct glyph_row *,
2811 enum glyph_row_area, int, int));
2812
2813 #if GLYPH_DEBUG
2814 static void x_check_font P_ ((struct frame *, XFontStruct *));
2815 #endif
2816
2817
2818 /* Append the list of glyph strings with head H and tail T to the list
2819 with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the result. */
2820
2821 static INLINE void
2822 x_append_glyph_string_lists (head, tail, h, t)
2823 struct glyph_string **head, **tail;
2824 struct glyph_string *h, *t;
2825 {
2826 if (h)
2827 {
2828 if (*head)
2829 (*tail)->next = h;
2830 else
2831 *head = h;
2832 h->prev = *tail;
2833 *tail = t;
2834 }
2835 }
2836
2837
2838 /* Prepend the list of glyph strings with head H and tail T to the
2839 list with head *HEAD and tail *TAIL. Set *HEAD and *TAIL to the
2840 result. */
2841
2842 static INLINE void
2843 x_prepend_glyph_string_lists (head, tail, h, t)
2844 struct glyph_string **head, **tail;
2845 struct glyph_string *h, *t;
2846 {
2847 if (h)
2848 {
2849 if (*head)
2850 (*head)->prev = t;
2851 else
2852 *tail = t;
2853 t->next = *head;
2854 *head = h;
2855 }
2856 }
2857
2858
2859 /* Append glyph string S to the list with head *HEAD and tail *TAIL.
2860 Set *HEAD and *TAIL to the resulting list. */
2861
2862 static INLINE void
2863 x_append_glyph_string (head, tail, s)
2864 struct glyph_string **head, **tail;
2865 struct glyph_string *s;
2866 {
2867 s->next = s->prev = NULL;
2868 x_append_glyph_string_lists (head, tail, s, s);
2869 }
2870
2871
2872 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
2873 face. */
2874
2875 static void
2876 x_set_cursor_gc (s)
2877 struct glyph_string *s;
2878 {
2879 if (s->font == FRAME_FONT (s->f)
2880 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
2881 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
2882 && !s->cmp)
2883 s->gc = s->f->output_data.w32->cursor_gc;
2884 else
2885 {
2886 /* Cursor on non-default face: must merge. */
2887 XGCValues xgcv;
2888 unsigned long mask;
2889
2890 xgcv.background = s->f->output_data.w32->cursor_pixel;
2891 xgcv.foreground = s->face->background;
2892
2893 /* If the glyph would be invisible, try a different foreground. */
2894 if (xgcv.foreground == xgcv.background)
2895 xgcv.foreground = s->face->foreground;
2896 if (xgcv.foreground == xgcv.background)
2897 xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
2898 if (xgcv.foreground == xgcv.background)
2899 xgcv.foreground = s->face->foreground;
2900
2901 /* Make sure the cursor is distinct from text in this face. */
2902 if (xgcv.background == s->face->background
2903 && xgcv.foreground == s->face->foreground)
2904 {
2905 xgcv.background = s->face->foreground;
2906 xgcv.foreground = s->face->background;
2907 }
2908
2909 IF_DEBUG (x_check_font (s->f, s->font));
2910 xgcv.font = s->font;
2911 mask = GCForeground | GCBackground | GCFont;
2912
2913 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2914 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2915 mask, &xgcv);
2916 else
2917 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2918 = XCreateGC (NULL, s->window, mask, &xgcv);
2919
2920 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2921 }
2922 }
2923
2924
2925 /* Set up S->gc of glyph string S for drawing text in mouse face. */
2926
2927 static void
2928 x_set_mouse_face_gc (s)
2929 struct glyph_string *s;
2930 {
2931 int face_id;
2932 struct face *face;
2933
2934 /* What face has to be used last for the mouse face? */
2935 face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
2936 face = FACE_FROM_ID (s->f, face_id);
2937 if (face == NULL)
2938 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2939
2940 if (s->first_glyph->type == CHAR_GLYPH)
2941 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
2942 else
2943 face_id = FACE_FOR_CHAR (s->f, face, 0);
2944 s->face = FACE_FROM_ID (s->f, face_id);
2945 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2946
2947 /* If font in this face is same as S->font, use it. */
2948 if (s->font == s->face->font)
2949 s->gc = s->face->gc;
2950 else
2951 {
2952 /* Otherwise construct scratch_cursor_gc with values from FACE
2953 but font FONT. */
2954 XGCValues xgcv;
2955 unsigned long mask;
2956
2957 xgcv.background = s->face->background;
2958 xgcv.foreground = s->face->foreground;
2959 IF_DEBUG (x_check_font (s->f, s->font));
2960 xgcv.font = s->font;
2961 mask = GCForeground | GCBackground | GCFont;
2962
2963 if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
2964 XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
2965 mask, &xgcv);
2966 else
2967 FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
2968 = XCreateGC (NULL, s->window, mask, &xgcv);
2969
2970 s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
2971 }
2972
2973 xassert (s->gc != 0);
2974 }
2975
2976
2977 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
2978 Faces to use in the mode line have already been computed when the
2979 matrix was built, so there isn't much to do, here. */
2980
2981 static INLINE void
2982 x_set_mode_line_face_gc (s)
2983 struct glyph_string *s;
2984 {
2985 s->gc = s->face->gc;
2986 }
2987
2988
2989 /* Set S->gc of glyph string S for drawing that glyph string. Set
2990 S->stippled_p to a non-zero value if the face of S has a stipple
2991 pattern. */
2992
2993 static INLINE void
2994 x_set_glyph_string_gc (s)
2995 struct glyph_string *s;
2996 {
2997 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
2998
2999 if (s->hl == DRAW_NORMAL_TEXT)
3000 {
3001 s->gc = s->face->gc;
3002 s->stippled_p = s->face->stipple != 0;
3003 }
3004 else if (s->hl == DRAW_INVERSE_VIDEO)
3005 {
3006 x_set_mode_line_face_gc (s);
3007 s->stippled_p = s->face->stipple != 0;
3008 }
3009 else if (s->hl == DRAW_CURSOR)
3010 {
3011 x_set_cursor_gc (s);
3012 s->stippled_p = 0;
3013 }
3014 else if (s->hl == DRAW_MOUSE_FACE)
3015 {
3016 x_set_mouse_face_gc (s);
3017 s->stippled_p = s->face->stipple != 0;
3018 }
3019 else if (s->hl == DRAW_IMAGE_RAISED
3020 || s->hl == DRAW_IMAGE_SUNKEN)
3021 {
3022 s->gc = s->face->gc;
3023 s->stippled_p = s->face->stipple != 0;
3024 }
3025 else
3026 {
3027 s->gc = s->face->gc;
3028 s->stippled_p = s->face->stipple != 0;
3029 }
3030
3031 /* GC must have been set. */
3032 xassert (s->gc != 0);
3033 }
3034
3035
3036 /* Return in *R the clipping rectangle for glyph string S. */
3037
3038 static void
3039 w32_get_glyph_string_clip_rect (s, r)
3040 struct glyph_string *s;
3041 RECT *r;
3042 {
3043 int r_height, r_width;
3044
3045 if (s->row->full_width_p)
3046 {
3047 /* Draw full-width. X coordinates are relative to S->w->left. */
3048 int canon_x = CANON_X_UNIT (s->f);
3049
3050 r->left = WINDOW_LEFT_MARGIN (s->w) * canon_x;
3051 r_width = XFASTINT (s->w->width) * canon_x;
3052
3053 if (FRAME_HAS_VERTICAL_SCROLL_BARS (s->f))
3054 {
3055 int width = FRAME_SCROLL_BAR_WIDTH (s->f) * canon_x;
3056 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (s->f))
3057 r->left -= width;
3058 }
3059
3060 r->left += FRAME_INTERNAL_BORDER_WIDTH (s->f);
3061
3062 /* Unless displaying a mode or menu bar line, which are always
3063 fully visible, clip to the visible part of the row. */
3064 if (s->w->pseudo_window_p)
3065 r_height = s->row->visible_height;
3066 else
3067 r_height = s->height;
3068 }
3069 else
3070 {
3071 /* This is a text line that may be partially visible. */
3072 r->left = WINDOW_AREA_TO_FRAME_PIXEL_X (s->w, s->area, 0);
3073 r_width = window_box_width (s->w, s->area);
3074 r_height = s->row->visible_height;
3075 }
3076
3077 /* If S draws overlapping rows, it's sufficient to use the top and
3078 bottom of the window for clipping because this glyph string
3079 intentionally draws over other lines. */
3080 if (s->for_overlaps_p)
3081 {
3082 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3083 r_height = window_text_bottom_y (s->w) - r->top;
3084 }
3085 else
3086 {
3087 /* Don't use S->y for clipping because it doesn't take partially
3088 visible lines into account. For example, it can be negative for
3089 partially visible lines at the top of a window. */
3090 if (!s->row->full_width_p
3091 && MATRIX_ROW_PARTIALLY_VISIBLE_AT_TOP_P (s->w, s->row))
3092 r->top = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (s->w);
3093 else
3094 r->top = max (0, s->row->y);
3095
3096 /* If drawing a tool-bar window, draw it over the internal border
3097 at the top of the window. */
3098 if (s->w == XWINDOW (s->f->tool_bar_window))
3099 r->top -= s->f->output_data.w32->internal_border_width;
3100 }
3101
3102 r->top = WINDOW_TO_FRAME_PIXEL_Y (s->w, r->top);
3103
3104 r->bottom = r->top + r_height;
3105 r->right = r->left + r_width;
3106 }
3107
3108
3109 /* Set clipping for output of glyph string S. S may be part of a mode
3110 line or menu if we don't have X toolkit support. */
3111
3112 static INLINE void
3113 x_set_glyph_string_clipping (s)
3114 struct glyph_string *s;
3115 {
3116 RECT r;
3117 w32_get_glyph_string_clip_rect (s, &r);
3118 w32_set_clip_rectangle (s->hdc, &r);
3119 }
3120
3121
3122 /* Compute left and right overhang of glyph string S. If S is a glyph
3123 string for a composition, assume overhangs don't exist. */
3124
3125 static INLINE void
3126 x_compute_glyph_string_overhangs (s)
3127 struct glyph_string *s;
3128 {
3129 /* TODO: Windows does not appear to have a method for
3130 getting this info without getting the ABC widths for each
3131 individual character and working it out manually. */
3132 }
3133
3134
3135 /* Compute overhangs and x-positions for glyph string S and its
3136 predecessors, or successors. X is the starting x-position for S.
3137 BACKWARD_P non-zero means process predecessors. */
3138
3139 static void
3140 x_compute_overhangs_and_x (s, x, backward_p)
3141 struct glyph_string *s;
3142 int x;
3143 int backward_p;
3144 {
3145 if (backward_p)
3146 {
3147 while (s)
3148 {
3149 x_compute_glyph_string_overhangs (s);
3150 x -= s->width;
3151 s->x = x;
3152 s = s->prev;
3153 }
3154 }
3155 else
3156 {
3157 while (s)
3158 {
3159 x_compute_glyph_string_overhangs (s);
3160 s->x = x;
3161 x += s->width;
3162 s = s->next;
3163 }
3164 }
3165 }
3166
3167
3168 /* Set *LEFT and *RIGHT to the left and right overhang of GLYPH on
3169 frame F. Overhangs of glyphs other than type CHAR_GLYPH are
3170 assumed to be zero. */
3171
3172 static void
3173 w32_get_glyph_overhangs (hdc, glyph, f, left, right)
3174 HDC hdc;
3175 struct glyph *glyph;
3176 struct frame *f;
3177 int *left, *right;
3178 {
3179 *left = *right = 0;
3180
3181 if (glyph->type == CHAR_GLYPH)
3182 {
3183 XFontStruct *font;
3184 struct face *face;
3185 wchar_t char2b;
3186 XCharStruct *pcm;
3187
3188 face = x_get_glyph_face_and_encoding (f, glyph, &char2b, NULL);
3189 font = face->font;
3190
3191 if (font
3192 && (pcm = w32_per_char_metric (font, &char2b,
3193 glyph->w32_font_type)))
3194 {
3195 if (pcm->rbearing > pcm->width)
3196 *right = pcm->rbearing - pcm->width;
3197 if (pcm->lbearing < 0)
3198 *left = -pcm->lbearing;
3199 }
3200 }
3201 }
3202
3203
3204 static void
3205 x_get_glyph_overhangs (glyph, f, left, right)
3206 struct glyph *glyph;
3207 struct frame *f;
3208 int *left, *right;
3209 {
3210 HDC hdc = get_frame_dc (f);
3211 /* Convert to unicode! */
3212 w32_get_glyph_overhangs (hdc, glyph, f, left, right);
3213 release_frame_dc (f, hdc);
3214 }
3215
3216
3217 /* Return the index of the first glyph preceding glyph string S that
3218 is overwritten by S because of S's left overhang. Value is -1
3219 if no glyphs are overwritten. */
3220
3221 static int
3222 x_left_overwritten (s)
3223 struct glyph_string *s;
3224 {
3225 int k;
3226
3227 if (s->left_overhang)
3228 {
3229 int x = 0, i;
3230 struct glyph *glyphs = s->row->glyphs[s->area];
3231 int first = s->first_glyph - glyphs;
3232
3233 for (i = first - 1; i >= 0 && x > -s->left_overhang; --i)
3234 x -= glyphs[i].pixel_width;
3235
3236 k = i + 1;
3237 }
3238 else
3239 k = -1;
3240
3241 return k;
3242 }
3243
3244
3245 /* Return the index of the first glyph preceding glyph string S that
3246 is overwriting S because of its right overhang. Value is -1 if no
3247 glyph in front of S overwrites S. */
3248
3249 static int
3250 x_left_overwriting (s)
3251 struct glyph_string *s;
3252 {
3253 int i, k, x;
3254 struct glyph *glyphs = s->row->glyphs[s->area];
3255 int first = s->first_glyph - glyphs;
3256
3257 k = -1;
3258 x = 0;
3259 for (i = first - 1; i >= 0; --i)
3260 {
3261 int left, right;
3262 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
3263 if (x + right > 0)
3264 k = i;
3265 x -= glyphs[i].pixel_width;
3266 }
3267
3268 return k;
3269 }
3270
3271
3272 /* Return the index of the last glyph following glyph string S that is
3273 not overwritten by S because of S's right overhang. Value is -1 if
3274 no such glyph is found. */
3275
3276 static int
3277 x_right_overwritten (s)
3278 struct glyph_string *s;
3279 {
3280 int k = -1;
3281
3282 if (s->right_overhang)
3283 {
3284 int x = 0, i;
3285 struct glyph *glyphs = s->row->glyphs[s->area];
3286 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3287 int end = s->row->used[s->area];
3288
3289 for (i = first; i < end && s->right_overhang > x; ++i)
3290 x += glyphs[i].pixel_width;
3291
3292 k = i;
3293 }
3294
3295 return k;
3296 }
3297
3298
3299 /* Return the index of the last glyph following glyph string S that
3300 overwrites S because of its left overhang. Value is negative
3301 if no such glyph is found. */
3302
3303 static int
3304 x_right_overwriting (s)
3305 struct glyph_string *s;
3306 {
3307 int i, k, x;
3308 int end = s->row->used[s->area];
3309 struct glyph *glyphs = s->row->glyphs[s->area];
3310 int first = (s->first_glyph - glyphs) + (s->cmp ? 1 : s->nchars);
3311
3312 k = -1;
3313 x = 0;
3314 for (i = first; i < end; ++i)
3315 {
3316 int left, right;
3317 w32_get_glyph_overhangs (s->hdc, glyphs + i, s->f, &left, &right);
3318 if (x - left < 0)
3319 k = i;
3320 x += glyphs[i].pixel_width;
3321 }
3322
3323 return k;
3324 }
3325
3326
3327 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
3328
3329 static INLINE void
3330 x_clear_glyph_string_rect (s, x, y, w, h)
3331 struct glyph_string *s;
3332 int x, y, w, h;
3333 {
3334 int real_x = x;
3335 int real_y = y;
3336 int real_w = w;
3337 int real_h = h;
3338 #if 0
3339 /* Take clipping into account. */
3340 if (s->gc->clip_mask == Rect)
3341 {
3342 real_x = max (real_x, s->gc->clip_rectangle.left);
3343 real_y = max (real_y, s->gc->clip_rectangle.top);
3344 real_w = min (real_w, s->gc->clip_rectangle.right
3345 - s->gc->clip_rectangle.left);
3346 real_h = min (real_h, s->gc->clip_rectangle.bottom
3347 - s->gc->clip_rectangle.top);
3348 }
3349 #endif
3350 w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
3351 real_w, real_h);
3352 }
3353
3354
3355 /* Draw the background of glyph_string S. If S->background_filled_p
3356 is non-zero don't draw it. FORCE_P non-zero means draw the
3357 background even if it wouldn't be drawn normally. This is used
3358 when a string preceding S draws into the background of S, or S
3359 contains the first component of a composition. */
3360
3361 static void
3362 x_draw_glyph_string_background (s, force_p)
3363 struct glyph_string *s;
3364 int force_p;
3365 {
3366 /* Nothing to do if background has already been drawn or if it
3367 shouldn't be drawn in the first place. */
3368 if (!s->background_filled_p)
3369 {
3370 int box_line_width = max (s->face->box_line_width, 0);
3371
3372 #if 0 /* TODO: stipple */
3373 if (s->stippled_p)
3374 {
3375 /* Fill background with a stipple pattern. */
3376 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
3377 XFillRectangle (s->display, s->window, s->gc, s->x,
3378 s->y + box_line_width,
3379 s->background_width,
3380 s->height - 2 * box_line_width);
3381 XSetFillStyle (s->display, s->gc, FillSolid);
3382 s->background_filled_p = 1;
3383 }
3384 else
3385 #endif
3386 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
3387 || s->font_not_found_p
3388 || s->extends_to_end_of_line_p
3389 || s->font->bdf
3390 || force_p)
3391 {
3392 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
3393 s->background_width,
3394 s->height - 2 * box_line_width);
3395 s->background_filled_p = 1;
3396 }
3397 }
3398 }
3399
3400
3401 /* Draw the foreground of glyph string S. */
3402
3403 static void
3404 x_draw_glyph_string_foreground (s)
3405 struct glyph_string *s;
3406 {
3407 int i, x;
3408 HFONT old_font;
3409
3410 /* If first glyph of S has a left box line, start drawing the text
3411 of S to the right of that box line. */
3412 if (s->face->box != FACE_NO_BOX
3413 && s->first_glyph->left_box_line_p)
3414 x = s->x + abs (s->face->box_line_width);
3415 else
3416 x = s->x;
3417
3418 if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
3419 SetBkMode (s->hdc, TRANSPARENT);
3420 else
3421 SetBkMode (s->hdc, OPAQUE);
3422
3423 SetTextColor (s->hdc, s->gc->foreground);
3424 SetBkColor (s->hdc, s->gc->background);
3425 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3426
3427 if (s->font && s->font->hfont)
3428 old_font = SelectObject (s->hdc, s->font->hfont);
3429
3430 /* Draw characters of S as rectangles if S's font could not be
3431 loaded. */
3432 if (s->font_not_found_p)
3433 {
3434 for (i = 0; i < s->nchars; ++i)
3435 {
3436 struct glyph *g = s->first_glyph + i;
3437
3438 w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
3439 s->height - 1);
3440 x += g->pixel_width;
3441 }
3442 }
3443 else
3444 {
3445 char *char1b = (char *) s->char2b;
3446 int boff = s->font_info->baseline_offset;
3447
3448 if (s->font_info->vertical_centering)
3449 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
3450
3451 /* If we can use 8-bit functions, condense S->char2b. */
3452 if (!s->two_byte_p)
3453 for (i = 0; i < s->nchars; ++i)
3454 char1b[i] = BYTE2 (s->char2b[i]);
3455
3456 /* Draw text with TextOut and friends. */
3457 W32_TEXTOUT (s, x, s->ybase - boff, s->char2b, s->nchars);
3458 }
3459 if (s->font && s->font->hfont)
3460 SelectObject (s->hdc, old_font);
3461 }
3462
3463 /* Draw the foreground of composite glyph string S. */
3464
3465 static void
3466 x_draw_composite_glyph_string_foreground (s)
3467 struct glyph_string *s;
3468 {
3469 int i, x;
3470 HFONT old_font;
3471
3472 /* If first glyph of S has a left box line, start drawing the text
3473 of S to the right of that box line. */
3474 if (s->face->box != FACE_NO_BOX
3475 && s->first_glyph->left_box_line_p)
3476 x = s->x + abs (s->face->box_line_width);
3477 else
3478 x = s->x;
3479
3480 /* S is a glyph string for a composition. S->gidx is the index of
3481 the first character drawn for glyphs of this composition.
3482 S->gidx == 0 means we are drawing the very first character of
3483 this composition. */
3484
3485 SetTextColor (s->hdc, s->gc->foreground);
3486 SetBkColor (s->hdc, s->gc->background);
3487 SetBkMode (s->hdc, TRANSPARENT);
3488 SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
3489
3490 if (s->font && s->font->hfont)
3491 old_font = SelectObject (s->hdc, s->font->hfont);
3492
3493 /* Draw a rectangle for the composition if the font for the very
3494 first character of the composition could not be loaded. */
3495 if (s->font_not_found_p)
3496 {
3497 if (s->gidx == 0)
3498 w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
3499 s->height - 1);
3500 }
3501 else
3502 {
3503 for (i = 0; i < s->nchars; i++, ++s->gidx)
3504 W32_TEXTOUT (s, x + s->cmp->offsets[s->gidx * 2],
3505 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
3506 s->char2b + i, 1);
3507 }
3508 if (s->font && s->font->hfont)
3509 SelectObject (s->hdc, old_font);
3510 }
3511
3512
3513 /* Brightness beyond which a color won't have its highlight brightness
3514 boosted.
3515
3516 Nominally, highlight colors for `3d' faces are calculated by
3517 brightening an object's color by a constant scale factor, but this
3518 doesn't yield good results for dark colors, so for colors who's
3519 brightness is less than this value (on a scale of 0-255) have to
3520 use an additional additive factor.
3521
3522 The value here is set so that the default menu-bar/mode-line color
3523 (grey75) will not have its highlights changed at all. */
3524 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
3525
3526
3527 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
3528 or DELTA. Try a color with RGB values multiplied by FACTOR first.
3529 If this produces the same color as COLOR, try a color where all RGB
3530 values have DELTA added. Return the allocated color in *COLOR.
3531 DISPLAY is the X display, CMAP is the colormap to operate on.
3532 Value is non-zero if successful. */
3533
3534 static int
3535 w32_alloc_lighter_color (f, color, factor, delta)
3536 struct frame *f;
3537 COLORREF *color;
3538 double factor;
3539 int delta;
3540 {
3541 COLORREF new;
3542 long bright;
3543
3544 /* On Windows, RGB values are 0-255, not 0-65535, so scale delta. */
3545 delta /= 256;
3546
3547 /* Change RGB values by specified FACTOR. Avoid overflow! */
3548 xassert (factor >= 0);
3549 new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
3550 min (0xff, factor * GetGValue (*color)),
3551 min (0xff, factor * GetBValue (*color)));
3552
3553 /* Calculate brightness of COLOR. */
3554 bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
3555 + GetBValue (*color)) / 6;
3556
3557 /* We only boost colors that are darker than
3558 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
3559 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
3560 /* Make an additive adjustment to NEW, because it's dark enough so
3561 that scaling by FACTOR alone isn't enough. */
3562 {
3563 /* How far below the limit this color is (0 - 1, 1 being darker). */
3564 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
3565 /* The additive adjustment. */
3566 int min_delta = delta * dimness * factor / 2;
3567
3568 if (factor < 1)
3569 new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
3570 max (0, min (0xff, min_delta - GetGValue (*color))),
3571 max (0, min (0xff, min_delta - GetBValue (*color))));
3572 else
3573 new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
3574 max (0, min (0xff, min_delta + GetGValue (*color))),
3575 max (0, min (0xff, min_delta + GetBValue (*color))));
3576 }
3577
3578 if (new == *color)
3579 new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
3580 max (0, min (0xff, delta + GetGValue (*color))),
3581 max (0, min (0xff, delta + GetBValue (*color))));
3582
3583 /* TODO: Map to palette and retry with delta if same? */
3584 /* TODO: Free colors (if using palette)? */
3585
3586 if (new == *color)
3587 return 0;
3588
3589 *color = new;
3590
3591 return 1;
3592 }
3593
3594
3595 /* Set up the foreground color for drawing relief lines of glyph
3596 string S. RELIEF is a pointer to a struct relief containing the GC
3597 with which lines will be drawn. Use a color that is FACTOR or
3598 DELTA lighter or darker than the relief's background which is found
3599 in S->f->output_data.x->relief_background. If such a color cannot
3600 be allocated, use DEFAULT_PIXEL, instead. */
3601
3602 static void
3603 w32_setup_relief_color (f, relief, factor, delta, default_pixel)
3604 struct frame *f;
3605 struct relief *relief;
3606 double factor;
3607 int delta;
3608 COLORREF default_pixel;
3609 {
3610 XGCValues xgcv;
3611 struct w32_output *di = f->output_data.w32;
3612 unsigned long mask = GCForeground;
3613 COLORREF pixel;
3614 COLORREF background = di->relief_background;
3615 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
3616
3617 /* TODO: Free colors (if using palette)? */
3618
3619 /* Allocate new color. */
3620 xgcv.foreground = default_pixel;
3621 pixel = background;
3622 if (w32_alloc_lighter_color (f, &pixel, factor, delta))
3623 {
3624 relief->allocated_p = 1;
3625 xgcv.foreground = relief->pixel = pixel;
3626 }
3627
3628 if (relief->gc == 0)
3629 {
3630 #if 0 /* TODO: stipple */
3631 xgcv.stipple = dpyinfo->gray;
3632 mask |= GCStipple;
3633 #endif
3634 relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
3635 }
3636 else
3637 XChangeGC (NULL, relief->gc, mask, &xgcv);
3638 }
3639
3640
3641 /* Set up colors for the relief lines around glyph string S. */
3642
3643 static void
3644 x_setup_relief_colors (s)
3645 struct glyph_string *s;
3646 {
3647 struct w32_output *di = s->f->output_data.w32;
3648 COLORREF color;
3649
3650 if (s->face->use_box_color_for_shadows_p)
3651 color = s->face->box_color;
3652 else if (s->first_glyph->type == IMAGE_GLYPH
3653 && s->img->pixmap
3654 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
3655 color = IMAGE_BACKGROUND (s->img, s->f, 0);
3656 else
3657 color = s->gc->background;
3658
3659 if (di->white_relief.gc == 0
3660 || color != di->relief_background)
3661 {
3662 di->relief_background = color;
3663 w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
3664 WHITE_PIX_DEFAULT (s->f));
3665 w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
3666 BLACK_PIX_DEFAULT (s->f));
3667 }
3668 }
3669
3670
3671 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
3672 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
3673 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
3674 relief. LEFT_P non-zero means draw a relief on the left side of
3675 the rectangle. RIGHT_P non-zero means draw a relief on the right
3676 side of the rectangle. CLIP_RECT is the clipping rectangle to use
3677 when drawing. */
3678
3679 static void
3680 w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
3681 raised_p, left_p, right_p, clip_rect)
3682 struct frame *f;
3683 int left_x, top_y, right_x, bottom_y, left_p, right_p, raised_p;
3684 RECT *clip_rect;
3685 {
3686 int i;
3687 XGCValues gc;
3688 HDC hdc = get_frame_dc (f);
3689
3690 if (raised_p)
3691 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
3692 else
3693 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
3694
3695 w32_set_clip_rectangle (hdc, clip_rect);
3696
3697 /* Top. */
3698 for (i = 0; i < width; ++i)
3699 w32_fill_area (f, hdc, gc.foreground,
3700 left_x + i * left_p, top_y + i,
3701 (right_x + 1 - i * right_p) - (left_x + i * left_p) + 1, 1);
3702
3703 /* Left. */
3704 if (left_p)
3705 for (i = 0; i < width; ++i)
3706 w32_fill_area (f, hdc, gc.foreground,
3707 left_x + i, top_y + i, 1,
3708 (bottom_y - i) - (top_y + i) + 2);
3709
3710 if (raised_p)
3711 gc.foreground = f->output_data.w32->black_relief.gc->foreground;
3712 else
3713 gc.foreground = f->output_data.w32->white_relief.gc->foreground;
3714
3715 /* Bottom. */
3716 for (i = 0; i < width; ++i)
3717 w32_fill_area (f, hdc, gc.foreground,
3718 left_x + i * left_p, bottom_y - i,
3719 (right_x - i * right_p) - (left_x + i * left_p) + 2, 1);
3720
3721 /* Right. */
3722 if (right_p)
3723 for (i = 0; i < width; ++i)
3724 w32_fill_area (f, hdc, gc.foreground,
3725 right_x - i, top_y + i + 1, 1,
3726 (bottom_y - i) - (top_y + i));
3727
3728 w32_set_clip_rectangle (hdc, NULL);
3729
3730 release_frame_dc (f, hdc);
3731 }
3732
3733
3734 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
3735 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
3736 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
3737 left side of the rectangle. RIGHT_P non-zero means draw a line
3738 on the right side of the rectangle. CLIP_RECT is the clipping
3739 rectangle to use when drawing. */
3740
3741 static void
3742 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3743 left_p, right_p, clip_rect)
3744 struct glyph_string *s;
3745 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3746 RECT *clip_rect;
3747 {
3748 w32_set_clip_rectangle (s->hdc, clip_rect);
3749
3750 /* Top. */
3751 w32_fill_area (s->f, s->hdc, s->face->box_color,
3752 left_x, top_y, right_x - left_x + 1, width);
3753
3754 /* Left. */
3755 if (left_p)
3756 {
3757 w32_fill_area (s->f, s->hdc, s->face->box_color,
3758 left_x, top_y, width, bottom_y - top_y + 1);
3759 }
3760
3761 /* Bottom. */
3762 w32_fill_area (s->f, s->hdc, s->face->box_color,
3763 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
3764
3765 /* Right. */
3766 if (right_p)
3767 {
3768 w32_fill_area (s->f, s->hdc, s->face->box_color,
3769 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
3770 }
3771
3772 w32_set_clip_rectangle (s->hdc, NULL);
3773 }
3774
3775
3776 /* Draw a box around glyph string S. */
3777
3778 static void
3779 x_draw_glyph_string_box (s)
3780 struct glyph_string *s;
3781 {
3782 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
3783 int left_p, right_p;
3784 struct glyph *last_glyph;
3785 RECT clip_rect;
3786
3787 last_x = window_box_right (s->w, s->area);
3788 if (s->row->full_width_p
3789 && !s->w->pseudo_window_p)
3790 {
3791 last_x += FRAME_X_RIGHT_FRINGE_WIDTH (s->f);
3792 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (s->f))
3793 last_x += FRAME_SCROLL_BAR_WIDTH (s->f) * CANON_X_UNIT (s->f);
3794 }
3795
3796 /* The glyph that may have a right box line. */
3797 last_glyph = (s->cmp || s->img
3798 ? s->first_glyph
3799 : s->first_glyph + s->nchars - 1);
3800
3801 width = abs (s->face->box_line_width);
3802 raised_p = s->face->box == FACE_RAISED_BOX;
3803 left_x = s->x;
3804 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
3805 ? last_x - 1
3806 : min (last_x, s->x + s->background_width) - 1));
3807 top_y = s->y;
3808 bottom_y = top_y + s->height - 1;
3809
3810 left_p = (s->first_glyph->left_box_line_p
3811 || (s->hl == DRAW_MOUSE_FACE
3812 && (s->prev == NULL
3813 || s->prev->hl != s->hl)));
3814 right_p = (last_glyph->right_box_line_p
3815 || (s->hl == DRAW_MOUSE_FACE
3816 && (s->next == NULL
3817 || s->next->hl != s->hl)));
3818
3819 w32_get_glyph_string_clip_rect (s, &clip_rect);
3820
3821 if (s->face->box == FACE_SIMPLE_BOX)
3822 w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3823 left_p, right_p, &clip_rect);
3824 else
3825 {
3826 x_setup_relief_colors (s);
3827 w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
3828 width, raised_p, left_p, right_p, &clip_rect);
3829 }
3830 }
3831
3832
3833 /* Draw foreground of image glyph string S. */
3834
3835 static void
3836 x_draw_image_foreground (s)
3837 struct glyph_string *s;
3838 {
3839 int x;
3840 int y = s->ybase - image_ascent (s->img, s->face);
3841
3842 /* If first glyph of S has a left box line, start drawing it to the
3843 right of that line. */
3844 if (s->face->box != FACE_NO_BOX
3845 && s->first_glyph->left_box_line_p)
3846 x = s->x + abs (s->face->box_line_width);
3847 else
3848 x = s->x;
3849
3850 /* If there is a margin around the image, adjust x- and y-position
3851 by that margin. */
3852 x += s->img->hmargin;
3853 y += s->img->vmargin;
3854
3855 SaveDC (s->hdc);
3856
3857 if (s->img->pixmap)
3858 {
3859 #if 0 /* TODO: image mask */
3860 if (s->img->mask)
3861 {
3862 /* We can't set both a clip mask and use XSetClipRectangles
3863 because the latter also sets a clip mask. We also can't
3864 trust on the shape extension to be available
3865 (XShapeCombineRegion). So, compute the rectangle to draw
3866 manually. */
3867 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
3868 | GCFunction);
3869 XGCValues xgcv;
3870 XRectangle clip_rect, image_rect, r;
3871
3872 xgcv.clip_mask = s->img->mask;
3873 xgcv.clip_x_origin = x;
3874 xgcv.clip_y_origin = y;
3875 xgcv.function = GXcopy;
3876 XChangeGC (s->display, s->gc, mask, &xgcv);
3877
3878 w32_get_glyph_string_clip_rect (s, &clip_rect);
3879 image_rect.x = x;
3880 image_rect.y = y;
3881 image_rect.width = s->img->width;
3882 image_rect.height = s->img->height;
3883 if (IntersectRect (&r, &clip_rect, &image_rect))
3884 XCopyArea (s->display, s->img->pixmap, s->window, s->gc,
3885 r.x - x, r.y - y, r.width, r.height, r.x, r.y);
3886 }
3887 else
3888 #endif
3889 {
3890 HDC compat_hdc = CreateCompatibleDC (s->hdc);
3891 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
3892 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
3893 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
3894 x_set_glyph_string_clipping (s);
3895
3896 SetTextColor (s->hdc, s->gc->foreground);
3897 SetBkColor (s->hdc, s->gc->background);
3898 #if 0 /* From w32bdf.c (which is from Meadow). */
3899 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3900 compat_hdc, 0, 0, SRCCOPY);
3901 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3902 compat_hdc, 0, 0, 0xB8074A);
3903 #else
3904 BitBlt (s->hdc, x, y, s->img->width, s->img->height,
3905 compat_hdc, 0, 0, 0xE20746);
3906 #endif
3907 SelectObject (s->hdc, orig_brush);
3908 DeleteObject (fg_brush);
3909 SelectObject (compat_hdc, orig_obj);
3910 DeleteDC (compat_hdc);
3911
3912 /* When the image has a mask, we can expect that at
3913 least part of a mouse highlight or a block cursor will
3914 be visible. If the image doesn't have a mask, make
3915 a block cursor visible by drawing a rectangle around
3916 the image. I believe it's looking better if we do
3917 nothing here for mouse-face. */
3918 if (s->hl == DRAW_CURSOR)
3919 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width - 1,
3920 s->img->height - 1);
3921 w32_set_clip_rectangle (s->hdc, NULL);
3922 }
3923 }
3924 else
3925 w32_draw_rectangle (s->hdc, s->gc, x, y, s->img->width -1,
3926 s->img->height - 1);
3927
3928 RestoreDC (s->hdc ,-1);
3929 }
3930
3931
3932
3933 /* Draw a relief around the image glyph string S. */
3934
3935 static void
3936 x_draw_image_relief (s)
3937 struct glyph_string *s;
3938 {
3939 int x0, y0, x1, y1, thick, raised_p;
3940 RECT r;
3941 int x;
3942 int y = s->ybase - image_ascent (s->img, s->face);
3943
3944 /* If first glyph of S has a left box line, start drawing it to the
3945 right of that line. */
3946 if (s->face->box != FACE_NO_BOX
3947 && s->first_glyph->left_box_line_p)
3948 x = s->x + abs (s->face->box_line_width);
3949 else
3950 x = s->x;
3951
3952 /* If there is a margin around the image, adjust x- and y-position
3953 by that margin. */
3954 x += s->img->hmargin;
3955 y += s->img->vmargin;
3956
3957 if (s->hl == DRAW_IMAGE_SUNKEN
3958 || s->hl == DRAW_IMAGE_RAISED)
3959 {
3960 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
3961 raised_p = s->hl == DRAW_IMAGE_RAISED;
3962 }
3963 else
3964 {
3965 thick = abs (s->img->relief);
3966 raised_p = s->img->relief > 0;
3967 }
3968
3969 x0 = x - thick;
3970 y0 = y - thick;
3971 x1 = x + s->img->width + thick - 1;
3972 y1 = y + s->img->height + thick - 1;
3973
3974 x_setup_relief_colors (s);
3975 w32_get_glyph_string_clip_rect (s, &r);
3976 w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 1, 1, &r);
3977 }
3978
3979
3980 /* Draw the foreground of image glyph string S to PIXMAP. */
3981
3982 static void
3983 w32_draw_image_foreground_1 (s, pixmap)
3984 struct glyph_string *s;
3985 HBITMAP pixmap;
3986 {
3987 HDC hdc = CreateCompatibleDC (s->hdc);
3988 HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
3989 int x;
3990 int y = s->ybase - s->y - image_ascent (s->img, s->face);
3991
3992 /* If first glyph of S has a left box line, start drawing it to the
3993 right of that line. */
3994 if (s->face->box != FACE_NO_BOX
3995 && s->first_glyph->left_box_line_p)
3996 x = abs (s->face->box_line_width);
3997 else
3998 x = 0;
3999
4000 /* If there is a margin around the image, adjust x- and y-position
4001 by that margin. */
4002 x += s->img->hmargin;
4003 y += s->img->vmargin;
4004
4005 if (s->img->pixmap)
4006 {
4007 #if 0 /* TODO: image mask */
4008 if (s->img->mask)
4009 {
4010 /* We can't set both a clip mask and use XSetClipRectangles
4011 because the latter also sets a clip mask. We also can't
4012 trust on the shape extension to be available
4013 (XShapeCombineRegion). So, compute the rectangle to draw
4014 manually. */
4015 unsigned long mask = (GCClipMask | GCClipXOrigin | GCClipYOrigin
4016 | GCFunction);
4017 XGCValues xgcv;
4018
4019 xgcv.clip_mask = s->img->mask;
4020 xgcv.clip_x_origin = x;
4021 xgcv.clip_y_origin = y;
4022 xgcv.function = GXcopy;
4023 XChangeGC (s->display, s->gc, mask, &xgcv);
4024
4025 XCopyArea (s->display, s->img->pixmap, pixmap, s->gc,
4026 0, 0, s->img->width, s->img->height, x, y);
4027 XSetClipMask (s->display, s->gc, None);
4028 }
4029 else
4030 #endif
4031 {
4032 HDC compat_hdc = CreateCompatibleDC (hdc);
4033 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
4034 HBRUSH orig_brush = SelectObject (hdc, fg_brush);
4035 HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
4036
4037 SetTextColor (hdc, s->gc->foreground);
4038 SetBkColor (hdc, s->gc->background);
4039 #if 0 /* From w32bdf.c (which is from Meadow). */
4040 BitBlt (hdc, x, y, s->img->width, s->img->height,
4041 compat_hdc, 0, 0, SRCCOPY);
4042 BitBlt (hdc, x, y, s->img->width, s->img->height,
4043 compat_hdc, 0, 0, 0xB8074A);
4044 #else
4045 BitBlt (hdc, x, y, s->img->width, s->img->height,
4046 compat_hdc, 0, 0, 0xE20746);
4047 #endif
4048 SelectObject (hdc, orig_brush);
4049 DeleteObject (fg_brush);
4050 SelectObject (compat_hdc, orig_obj);
4051 DeleteDC (compat_hdc);
4052
4053 /* When the image has a mask, we can expect that at
4054 least part of a mouse highlight or a block cursor will
4055 be visible. If the image doesn't have a mask, make
4056 a block cursor visible by drawing a rectangle around
4057 the image. I believe it's looking better if we do
4058 nothing here for mouse-face. */
4059 if (s->hl == DRAW_CURSOR)
4060 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
4061 s->img->height - 1);
4062 }
4063 }
4064 else
4065 w32_draw_rectangle (hdc, s->gc, x, y, s->img->width - 1,
4066 s->img->height - 1);
4067
4068 SelectObject (hdc, orig_hdc_obj);
4069 DeleteDC (hdc);
4070 }
4071
4072
4073 /* Draw part of the background of glyph string S. X, Y, W, and H
4074 give the rectangle to draw. */
4075
4076 static void
4077 x_draw_glyph_string_bg_rect (s, x, y, w, h)
4078 struct glyph_string *s;
4079 int x, y, w, h;
4080 {
4081 #if 0 /* TODO: stipple */
4082 if (s->stippled_p)
4083 {
4084 /* Fill background with a stipple pattern. */
4085 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4086 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
4087 XSetFillStyle (s->display, s->gc, FillSolid);
4088 }
4089 else
4090 #endif
4091 x_clear_glyph_string_rect (s, x, y, w, h);
4092 }
4093
4094
4095 /* Draw image glyph string S.
4096
4097 s->y
4098 s->x +-------------------------
4099 | s->face->box
4100 |
4101 | +-------------------------
4102 | | s->img->vmargin
4103 | |
4104 | | +-------------------
4105 | | | the image
4106
4107 */
4108
4109 static void
4110 x_draw_image_glyph_string (s)
4111 struct glyph_string *s;
4112 {
4113 int x, y;
4114 int box_line_hwidth = abs (s->face->box_line_width);
4115 int box_line_vwidth = max (s->face->box_line_width, 0);
4116 int height;
4117 HBITMAP pixmap = 0;
4118
4119 height = s->height - 2 * box_line_vwidth;
4120
4121 /* Fill background with face under the image. Do it only if row is
4122 taller than image or if image has a clip mask to reduce
4123 flickering. */
4124 s->stippled_p = s->face->stipple != 0;
4125 if (height > s->img->height
4126 || s->img->hmargin
4127 || s->img->vmargin
4128 #if 0 /* TODO: image mask */
4129 || s->img->mask
4130 #endif
4131 || s->img->pixmap == 0
4132 || s->width != s->background_width)
4133 {
4134 if (box_line_hwidth && s->first_glyph->left_box_line_p)
4135 x = s->x + box_line_hwidth;
4136 else
4137 x = s->x;
4138
4139 y = s->y + box_line_vwidth;
4140 #if 0 /* TODO: image mask */
4141 if (s->img->mask)
4142 {
4143 /* Create a pixmap as large as the glyph string. Fill it
4144 with the background color. Copy the image to it, using
4145 its mask. Copy the temporary pixmap to the display. */
4146 Screen *screen = FRAME_X_SCREEN (s->f);
4147 int depth = DefaultDepthOfScreen (screen);
4148
4149 /* Create a pixmap as large as the glyph string. */
4150 pixmap = XCreatePixmap (s->display, s->window,
4151 s->background_width,
4152 s->height, depth);
4153
4154 /* Don't clip in the following because we're working on the
4155 pixmap. */
4156 XSetClipMask (s->display, s->gc, None);
4157
4158 /* Fill the pixmap with the background color/stipple. */
4159 if (s->stippled_p)
4160 {
4161 /* Fill background with a stipple pattern. */
4162 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
4163 XFillRectangle (s->display, pixmap, s->gc,
4164 0, 0, s->background_width, s->height);
4165 XSetFillStyle (s->display, s->gc, FillSolid);
4166 }
4167 else
4168 {
4169 XGCValues xgcv;
4170 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
4171 &xgcv);
4172 XSetForeground (s->display, s->gc, xgcv.background);
4173 XFillRectangle (s->display, pixmap, s->gc,
4174 0, 0, s->background_width, s->height);
4175 XSetForeground (s->display, s->gc, xgcv.foreground);
4176 }
4177 }
4178 else
4179 #endif
4180 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
4181
4182 s->background_filled_p = 1;
4183 }
4184
4185 /* Draw the foreground. */
4186 if (pixmap != 0)
4187 {
4188 w32_draw_image_foreground_1 (s, pixmap);
4189 x_set_glyph_string_clipping (s);
4190 {
4191 HDC compat_hdc = CreateCompatibleDC (s->hdc);
4192 HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
4193 HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
4194 HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
4195
4196 SetTextColor (s->hdc, s->gc->foreground);
4197 SetBkColor (s->hdc, s->gc->background);
4198 #if 0 /* From w32bdf.c (which is from Meadow). */
4199 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
4200 compat_hdc, 0, 0, SRCCOPY);
4201 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
4202 compat_hdc, 0, 0, 0xB8074A);
4203 #else
4204 BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
4205 compat_hdc, 0, 0, 0xE20746);
4206 #endif
4207 SelectObject (s->hdc, orig_brush);
4208 DeleteObject (fg_brush);
4209 SelectObject (compat_hdc, orig_obj);
4210 DeleteDC (compat_hdc);
4211 }
4212 DeleteObject (pixmap);
4213 pixmap = 0;
4214 }
4215 else
4216 x_draw_image_foreground (s);
4217
4218 /* If we must draw a relief around the image, do it. */
4219 if (s->img->relief
4220 || s->hl == DRAW_IMAGE_RAISED
4221 || s->hl == DRAW_IMAGE_SUNKEN)
4222 x_draw_image_relief (s);
4223 }
4224
4225
4226 /* Draw stretch glyph string S. */
4227
4228 static void
4229 x_draw_stretch_glyph_string (s)
4230 struct glyph_string *s;
4231 {
4232 xassert (s->first_glyph->type == STRETCH_GLYPH);
4233 s->stippled_p = s->face->stipple != 0;
4234
4235 if (s->hl == DRAW_CURSOR
4236 && !x_stretch_cursor_p)
4237 {
4238 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
4239 as wide as the stretch glyph. */
4240 int width = min (CANON_X_UNIT (s->f), s->background_width);
4241
4242 /* Draw cursor. */
4243 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
4244
4245 /* Clear rest using the GC of the original non-cursor face. */
4246 if (width < s->background_width)
4247 {
4248 XGCValues *gc = s->face->gc;
4249 int x = s->x + width, y = s->y;
4250 int w = s->background_width - width, h = s->height;
4251 RECT r;
4252 HDC hdc = s->hdc;
4253
4254 if (s->row->mouse_face_p
4255 && cursor_in_mouse_face_p (s->w))
4256 {
4257 x_set_mouse_face_gc (s);
4258 gc = s->gc;
4259 }
4260 else
4261 gc = s->face->gc;
4262
4263 w32_get_glyph_string_clip_rect (s, &r);
4264 w32_set_clip_rectangle (hdc, &r);
4265
4266 #if 0 /* TODO: stipple */
4267 if (s->face->stipple)
4268 {
4269 /* Fill background with a stipple pattern. */
4270 XSetFillStyle (s->display, gc, FillOpaqueStippled);
4271 XFillRectangle (s->display, s->window, gc, x, y, w, h);
4272 XSetFillStyle (s->display, gc, FillSolid);
4273 }
4274 else
4275 #endif
4276 {
4277 w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
4278 }
4279 }
4280 }
4281 else if (!s->background_filled_p)
4282 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
4283 s->height);
4284
4285 s->background_filled_p = 1;
4286 }
4287
4288
4289 /* Draw glyph string S. */
4290
4291 static void
4292 x_draw_glyph_string (s)
4293 struct glyph_string *s;
4294 {
4295 int relief_drawn_p = 0;
4296
4297 /* If S draws into the background of its successor, draw the
4298 background of the successor first so that S can draw into it.
4299 This makes S->next use XDrawString instead of XDrawImageString. */
4300 if (s->next && s->right_overhang && !s->for_overlaps_p)
4301 {
4302 xassert (s->next->img == NULL);
4303 x_set_glyph_string_gc (s->next);
4304 x_set_glyph_string_clipping (s->next);
4305 x_draw_glyph_string_background (s->next, 1);
4306 }
4307
4308 /* Set up S->gc, set clipping and draw S. */
4309 x_set_glyph_string_gc (s);
4310
4311 /* Draw relief (if any) in advance for char/composition so that the
4312 glyph string can be drawn over it. */
4313 if (!s->for_overlaps_p
4314 && s->face->box != FACE_NO_BOX
4315 && (s->first_glyph->type == CHAR_GLYPH
4316 || s->first_glyph->type == COMPOSITE_GLYPH))
4317
4318 {
4319 x_set_glyph_string_clipping (s);
4320 x_draw_glyph_string_background (s, 1);
4321 x_draw_glyph_string_box (s);
4322 x_set_glyph_string_clipping (s);
4323 relief_drawn_p = 1;
4324 }
4325 else
4326 x_set_glyph_string_clipping (s);
4327
4328 switch (s->first_glyph->type)
4329 {
4330 case IMAGE_GLYPH:
4331 x_draw_image_glyph_string (s);
4332 break;
4333
4334 case STRETCH_GLYPH:
4335 x_draw_stretch_glyph_string (s);
4336 break;
4337
4338 case CHAR_GLYPH:
4339 if (s->for_overlaps_p)
4340 s->background_filled_p = 1;
4341 else
4342 x_draw_glyph_string_background (s, 0);
4343 x_draw_glyph_string_foreground (s);
4344 break;
4345
4346 case COMPOSITE_GLYPH:
4347 if (s->for_overlaps_p || s->gidx > 0)
4348 s->background_filled_p = 1;
4349 else
4350 x_draw_glyph_string_background (s, 1);
4351 x_draw_composite_glyph_string_foreground (s);
4352 break;
4353
4354 default:
4355 abort ();
4356 }
4357
4358 if (!s->for_overlaps_p)
4359 {
4360 /* Draw underline. */
4361 if (s->face->underline_p
4362 && (s->font->bdf || !s->font->tm.tmUnderlined))
4363 {
4364 unsigned long h = 1;
4365 unsigned long dy = s->height - h;
4366
4367 /* TODO: Use font information for positioning and thickness
4368 of underline. See OUTLINETEXTMETRIC, and xterm.c. */
4369 if (s->face->underline_defaulted_p)
4370 {
4371 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
4372 s->y + dy, s->width, 1);
4373 }
4374 else
4375 {
4376 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4377 s->y + dy, s->width, 1);
4378 }
4379 }
4380
4381 /* Draw overline. */
4382 if (s->face->overline_p)
4383 {
4384 unsigned long dy = 0, h = 1;
4385
4386 if (s->face->overline_color_defaulted_p)
4387 {
4388 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
4389 s->y + dy, s->width, h);
4390 }
4391 else
4392 {
4393 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4394 s->y + dy, s->width, h);
4395 }
4396 }
4397
4398 /* Draw strike-through. */
4399 if (s->face->strike_through_p
4400 && (s->font->bdf || !s->font->tm.tmStruckOut))
4401 {
4402 unsigned long h = 1;
4403 unsigned long dy = (s->height - h) / 2;
4404
4405 if (s->face->strike_through_color_defaulted_p)
4406 {
4407 w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
4408 s->width, h);
4409 }
4410 else
4411 {
4412 w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
4413 s->y + dy, s->width, h);
4414 }
4415 }
4416
4417 /* Draw relief. */
4418 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
4419 x_draw_glyph_string_box (s);
4420 }
4421
4422 /* Reset clipping. */
4423 w32_set_clip_rectangle (s->hdc, NULL);
4424 }
4425
4426
4427 static int x_fill_composite_glyph_string P_ ((struct glyph_string *,
4428 struct face **, int));
4429
4430
4431 /* Fill glyph string S with composition components specified by S->cmp.
4432
4433 FACES is an array of faces for all components of this composition.
4434 S->gidx is the index of the first component for S.
4435 OVERLAPS_P non-zero means S should draw the foreground only, and
4436 use its physical height for clipping.
4437
4438 Value is the index of a component not in S. */
4439
4440 static int
4441 x_fill_composite_glyph_string (s, faces, overlaps_p)
4442 struct glyph_string *s;
4443 struct face **faces;
4444 int overlaps_p;
4445 {
4446 int i;
4447
4448 xassert (s);
4449
4450 s->for_overlaps_p = overlaps_p;
4451
4452 s->face = faces[s->gidx];
4453 s->font = s->face->font;
4454 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4455
4456 /* For all glyphs of this composition, starting at the offset
4457 S->gidx, until we reach the end of the definition or encounter a
4458 glyph that requires the different face, add it to S. */
4459 ++s->nchars;
4460 for (i = s->gidx + 1; i < s->cmp->glyph_len && faces[i] == s->face; ++i)
4461 ++s->nchars;
4462
4463 /* All glyph strings for the same composition has the same width,
4464 i.e. the width set for the first component of the composition. */
4465
4466 s->width = s->first_glyph->pixel_width;
4467
4468 /* If the specified font could not be loaded, use the frame's
4469 default font, but record the fact that we couldn't load it in
4470 the glyph string so that we can draw rectangles for the
4471 characters of the glyph string. */
4472 if (s->font == NULL)
4473 {
4474 s->font_not_found_p = 1;
4475 s->font = FRAME_FONT (s->f);
4476 }
4477
4478 /* Adjust base line for subscript/superscript text. */
4479 s->ybase += s->first_glyph->voffset;
4480
4481 xassert (s->face && s->face->gc);
4482
4483 /* This glyph string must always be drawn with 16-bit functions. */
4484 s->two_byte_p = 1;
4485
4486 return s->gidx + s->nchars;
4487 }
4488
4489
4490 /* Fill glyph string S from a sequence of character glyphs.
4491
4492 FACE_ID is the face id of the string. START is the index of the
4493 first glyph to consider, END is the index of the last + 1.
4494 OVERLAPS_P non-zero means S should draw the foreground only, and
4495 use its physical height for clipping.
4496
4497 Value is the index of the first glyph not in S. */
4498
4499 static int
4500 x_fill_glyph_string (s, face_id, start, end, overlaps_p)
4501 struct glyph_string *s;
4502 int face_id;
4503 int start, end, overlaps_p;
4504 {
4505 struct glyph *glyph, *last;
4506 int voffset;
4507 int glyph_not_available_p;
4508
4509 xassert (s->f == XFRAME (s->w->frame));
4510 xassert (s->nchars == 0);
4511 xassert (start >= 0 && end > start);
4512
4513 s->for_overlaps_p = overlaps_p;
4514 glyph = s->row->glyphs[s->area] + start;
4515 last = s->row->glyphs[s->area] + end;
4516 voffset = glyph->voffset;
4517
4518 glyph_not_available_p = glyph->glyph_not_available_p;
4519
4520 while (glyph < last
4521 && glyph->type == CHAR_GLYPH
4522 && glyph->voffset == voffset
4523 /* Same face id implies same font, nowadays. */
4524 && glyph->face_id == face_id
4525 && glyph->glyph_not_available_p == glyph_not_available_p)
4526 {
4527 int two_byte_p;
4528
4529 s->face = x_get_glyph_face_and_encoding (s->f, glyph,
4530 s->char2b + s->nchars,
4531 &two_byte_p);
4532 s->two_byte_p = two_byte_p;
4533 ++s->nchars;
4534 xassert (s->nchars <= end - start);
4535 s->width += glyph->pixel_width;
4536 ++glyph;
4537 }
4538
4539 s->font = s->face->font;
4540 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4541
4542 /* If the specified font could not be loaded, use the frame's font,
4543 but record the fact that we couldn't load it in
4544 S->font_not_found_p so that we can draw rectangles for the
4545 characters of the glyph string. */
4546 if (s->font == NULL || glyph_not_available_p)
4547 {
4548 s->font_not_found_p = 1;
4549 s->font = FRAME_FONT (s->f);
4550 }
4551
4552 /* Adjust base line for subscript/superscript text. */
4553 s->ybase += voffset;
4554
4555 xassert (s->face && s->face->gc);
4556 return glyph - s->row->glyphs[s->area];
4557 }
4558
4559
4560 /* Fill glyph string S from image glyph S->first_glyph. */
4561
4562 static void
4563 x_fill_image_glyph_string (s)
4564 struct glyph_string *s;
4565 {
4566 xassert (s->first_glyph->type == IMAGE_GLYPH);
4567 s->img = IMAGE_FROM_ID (s->f, s->first_glyph->u.img_id);
4568 xassert (s->img);
4569 s->face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
4570 s->font = s->face->font;
4571 s->width = s->first_glyph->pixel_width;
4572
4573 /* Adjust base line for subscript/superscript text. */
4574 s->ybase += s->first_glyph->voffset;
4575 }
4576
4577
4578 /* Fill glyph string S from a sequence of stretch glyphs.
4579
4580 ROW is the glyph row in which the glyphs are found, AREA is the
4581 area within the row. START is the index of the first glyph to
4582 consider, END is the index of the last + 1.
4583
4584 Value is the index of the first glyph not in S. */
4585
4586 static int
4587 x_fill_stretch_glyph_string (s, row, area, start, end)
4588 struct glyph_string *s;
4589 struct glyph_row *row;
4590 enum glyph_row_area area;
4591 int start, end;
4592 {
4593 struct glyph *glyph, *last;
4594 int voffset, face_id;
4595
4596 xassert (s->first_glyph->type == STRETCH_GLYPH);
4597
4598 glyph = s->row->glyphs[s->area] + start;
4599 last = s->row->glyphs[s->area] + end;
4600 face_id = glyph->face_id;
4601 s->face = FACE_FROM_ID (s->f, face_id);
4602 s->font = s->face->font;
4603 s->font_info = FONT_INFO_FROM_ID (s->f, s->face->font_info_id);
4604 s->width = glyph->pixel_width;
4605 voffset = glyph->voffset;
4606
4607 for (++glyph;
4608 (glyph < last
4609 && glyph->type == STRETCH_GLYPH
4610 && glyph->voffset == voffset
4611 && glyph->face_id == face_id);
4612 ++glyph)
4613 s->width += glyph->pixel_width;
4614
4615 /* Adjust base line for subscript/superscript text. */
4616 s->ybase += voffset;
4617
4618 xassert (s->face);
4619 return glyph - s->row->glyphs[s->area];
4620 }
4621
4622
4623 /* Initialize glyph string S. CHAR2B is a suitably allocated vector
4624 of XChar2b structures for S; it can't be allocated in
4625 x_init_glyph_string because it must be allocated via `alloca'. W
4626 is the window on which S is drawn. ROW and AREA are the glyph row
4627 and area within the row from which S is constructed. START is the
4628 index of the first glyph structure covered by S. HL is a
4629 face-override for drawing S. */
4630
4631 static void
4632 w32_init_glyph_string (s, hdc, char2b, w, row, area, start, hl)
4633 struct glyph_string *s;
4634 HDC hdc;
4635 wchar_t *char2b;
4636 struct window *w;
4637 struct glyph_row *row;
4638 enum glyph_row_area area;
4639 int start;
4640 enum draw_glyphs_face hl;
4641 {
4642 bzero (s, sizeof *s);
4643 s->w = w;
4644 s->f = XFRAME (w->frame);
4645 s->hdc = hdc;
4646 s->window = FRAME_W32_WINDOW (s->f);
4647 s->char2b = char2b;
4648 s->hl = hl;
4649 s->row = row;
4650 s->area = area;
4651 s->first_glyph = row->glyphs[area] + start;
4652 s->height = row->height;
4653 s->y = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4654
4655 /* Display the internal border below the tool-bar window. */
4656 if (s->w == XWINDOW (s->f->tool_bar_window))
4657 s->y -= s->f->output_data.w32->internal_border_width;
4658
4659 s->ybase = s->y + row->ascent;
4660 }
4661
4662
4663 /* Set background width of glyph string S. START is the index of the
4664 first glyph following S. LAST_X is the right-most x-position + 1
4665 in the drawing area. */
4666
4667 static INLINE void
4668 x_set_glyph_string_background_width (s, start, last_x)
4669 struct glyph_string *s;
4670 int start;
4671 int last_x;
4672 {
4673 /* If the face of this glyph string has to be drawn to the end of
4674 the drawing area, set S->extends_to_end_of_line_p. */
4675 struct face *default_face = FACE_FROM_ID (s->f, DEFAULT_FACE_ID);
4676
4677 if (start == s->row->used[s->area]
4678 && s->area == TEXT_AREA
4679 && ((s->hl == DRAW_NORMAL_TEXT
4680 && (s->row->fill_line_p
4681 || s->face->background != default_face->background
4682 || s->face->stipple != default_face->stipple
4683 || s->row->mouse_face_p))
4684 || s->hl == DRAW_MOUSE_FACE
4685 || ((s->hl == DRAW_IMAGE_RAISED || s->hl == DRAW_IMAGE_SUNKEN)
4686 && s->row->fill_line_p)))
4687 s->extends_to_end_of_line_p = 1;
4688
4689 /* If S extends its face to the end of the line, set its
4690 background_width to the distance to the right edge of the drawing
4691 area. */
4692 if (s->extends_to_end_of_line_p)
4693 s->background_width = last_x - s->x + 1;
4694 else
4695 s->background_width = s->width;
4696 }
4697
4698
4699 /* Add a glyph string for a stretch glyph to the list of strings
4700 between HEAD and TAIL. START is the index of the stretch glyph in
4701 row area AREA of glyph row ROW. END is the index of the last glyph
4702 in that glyph row area. X is the current output position assigned
4703 to the new glyph string constructed. HL overrides that face of the
4704 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4705 is the right-most x-position of the drawing area. */
4706
4707 #define BUILD_STRETCH_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4708 do \
4709 { \
4710 s = (struct glyph_string *) alloca (sizeof *s); \
4711 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4712 START = x_fill_stretch_glyph_string (s, ROW, AREA, START, END); \
4713 x_append_glyph_string (&HEAD, &TAIL, s); \
4714 s->x = (X); \
4715 } \
4716 while (0)
4717
4718
4719 /* Add a glyph string for an image glyph to the list of strings
4720 between HEAD and TAIL. START is the index of the image glyph in
4721 row area AREA of glyph row ROW. END is the index of the last glyph
4722 in that glyph row area. X is the current output position assigned
4723 to the new glyph string constructed. HL overrides that face of the
4724 glyph; e.g. it is DRAW_CURSOR if a cursor has to be drawn. LAST_X
4725 is the right-most x-position of the drawing area. */
4726
4727 #define BUILD_IMAGE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X) \
4728 do \
4729 { \
4730 s = (struct glyph_string *) alloca (sizeof *s); \
4731 w32_init_glyph_string (s, hdc, NULL, W, ROW, AREA, START, HL); \
4732 x_fill_image_glyph_string (s); \
4733 x_append_glyph_string (&HEAD, &TAIL, s); \
4734 ++START; \
4735 s->x = (X); \
4736 } \
4737 while (0)
4738
4739
4740 /* Add a glyph string for a sequence of character glyphs to the list
4741 of strings between HEAD and TAIL. START is the index of the first
4742 glyph in row area AREA of glyph row ROW that is part of the new
4743 glyph string. END is the index of the last glyph in that glyph row
4744 area. X is the current output position assigned to the new glyph
4745 string constructed. HL overrides that face of the glyph; e.g. it
4746 is DRAW_CURSOR if a cursor has to be drawn. LAST_X is the
4747 right-most x-position of the drawing area. */
4748
4749 #define BUILD_CHAR_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4750 do \
4751 { \
4752 int c, face_id; \
4753 wchar_t *char2b; \
4754 \
4755 c = (ROW)->glyphs[AREA][START].u.ch; \
4756 face_id = (ROW)->glyphs[AREA][START].face_id; \
4757 \
4758 s = (struct glyph_string *) alloca (sizeof *s); \
4759 char2b = (wchar_t *) alloca ((END - START) * sizeof *char2b); \
4760 w32_init_glyph_string (s, hdc, char2b, W, ROW, AREA, START, HL); \
4761 x_append_glyph_string (&HEAD, &TAIL, s); \
4762 s->x = (X); \
4763 START = x_fill_glyph_string (s, face_id, START, END, \
4764 OVERLAPS_P); \
4765 } \
4766 while (0)
4767
4768
4769 /* Add a glyph string for a composite sequence to the list of strings
4770 between HEAD and TAIL. START is the index of the first glyph in
4771 row area AREA of glyph row ROW that is part of the new glyph
4772 string. END is the index of the last glyph in that glyph row area.
4773 X is the current output position assigned to the new glyph string
4774 constructed. HL overrides that face of the glyph; e.g. it is
4775 DRAW_CURSOR if a cursor has to be drawn. LAST_X is the right-most
4776 x-position of the drawing area. */
4777
4778 #define BUILD_COMPOSITE_GLYPH_STRING(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4779 do { \
4780 int cmp_id = (ROW)->glyphs[AREA][START].u.cmp_id; \
4781 int face_id = (ROW)->glyphs[AREA][START].face_id; \
4782 struct face *base_face = FACE_FROM_ID (XFRAME (w->frame), face_id); \
4783 struct composition *cmp = composition_table[cmp_id]; \
4784 int glyph_len = cmp->glyph_len; \
4785 wchar_t *char2b; \
4786 struct face **faces; \
4787 struct glyph_string *first_s = NULL; \
4788 int n; \
4789 \
4790 base_face = base_face->ascii_face; \
4791 char2b = (wchar_t *) alloca ((sizeof *char2b) * glyph_len); \
4792 faces = (struct face **) alloca ((sizeof *faces) * glyph_len); \
4793 /* At first, fill in `char2b' and `faces'. */ \
4794 for (n = 0; n < glyph_len; n++) \
4795 { \
4796 int c = COMPOSITION_GLYPH (cmp, n); \
4797 int this_face_id = FACE_FOR_CHAR (XFRAME (w->frame), base_face, c); \
4798 faces[n] = FACE_FROM_ID (XFRAME (w->frame), this_face_id); \
4799 x_get_char_face_and_encoding (XFRAME (w->frame), c, \
4800 this_face_id, char2b + n, 1); \
4801 } \
4802 \
4803 /* Make glyph_strings for each glyph sequence that is drawable by \
4804 the same face, and append them to HEAD/TAIL. */ \
4805 for (n = 0; n < cmp->glyph_len;) \
4806 { \
4807 s = (struct glyph_string *) alloca (sizeof *s); \
4808 w32_init_glyph_string (s, hdc, char2b + n, W, ROW, AREA, START, HL); \
4809 x_append_glyph_string (&(HEAD), &(TAIL), s); \
4810 s->cmp = cmp; \
4811 s->gidx = n; \
4812 s->x = (X); \
4813 \
4814 if (n == 0) \
4815 first_s = s; \
4816 \
4817 n = x_fill_composite_glyph_string (s, faces, OVERLAPS_P); \
4818 } \
4819 \
4820 ++START; \
4821 s = first_s; \
4822 } while (0)
4823
4824
4825 /* Build a list of glyph strings between HEAD and TAIL for the glyphs
4826 of AREA of glyph row ROW on window W between indices START and END.
4827 HL overrides the face for drawing glyph strings, e.g. it is
4828 DRAW_CURSOR to draw a cursor. X and LAST_X are start and end
4829 x-positions of the drawing area.
4830
4831 This is an ugly monster macro construct because we must use alloca
4832 to allocate glyph strings (because x_draw_glyphs can be called
4833 asynchronously). */
4834
4835 #define BUILD_GLYPH_STRINGS(hdc, W, ROW, AREA, START, END, HEAD, TAIL, HL, X, LAST_X, OVERLAPS_P) \
4836 do \
4837 { \
4838 HEAD = TAIL = NULL; \
4839 while (START < END) \
4840 { \
4841 struct glyph *first_glyph = (ROW)->glyphs[AREA] + START; \
4842 switch (first_glyph->type) \
4843 { \
4844 case CHAR_GLYPH: \
4845 BUILD_CHAR_GLYPH_STRINGS (hdc, W, ROW, AREA, START, END, \
4846 HEAD, TAIL, HL, X, LAST_X, \
4847 OVERLAPS_P); \
4848 break; \
4849 \
4850 case COMPOSITE_GLYPH: \
4851 BUILD_COMPOSITE_GLYPH_STRING (hdc, W, ROW, AREA, START, \
4852 END, HEAD, TAIL, HL, X, \
4853 LAST_X, OVERLAPS_P); \
4854 break; \
4855 \
4856 case STRETCH_GLYPH: \
4857 BUILD_STRETCH_GLYPH_STRING (hdc, W, ROW, AREA, START, END,\
4858 HEAD, TAIL, HL, X, LAST_X); \
4859 break; \
4860 \
4861 case IMAGE_GLYPH: \
4862 BUILD_IMAGE_GLYPH_STRING (hdc, W, ROW, AREA, START, END, \
4863 HEAD, TAIL, HL, X, LAST_X); \
4864 break; \
4865 \
4866 default: \
4867 abort (); \
4868 } \
4869 \
4870 x_set_glyph_string_background_width (s, START, LAST_X); \
4871 (X) += s->width; \
4872 } \
4873 } \
4874 while (0)
4875
4876
4877 /* Draw glyphs between START and END in AREA of ROW on window W,
4878 starting at x-position X. X is relative to AREA in W. HL is a
4879 face-override with the following meaning:
4880
4881 DRAW_NORMAL_TEXT draw normally
4882 DRAW_CURSOR draw in cursor face
4883 DRAW_MOUSE_FACE draw in mouse face.
4884 DRAW_INVERSE_VIDEO draw in mode line face
4885 DRAW_IMAGE_SUNKEN draw an image with a sunken relief around it
4886 DRAW_IMAGE_RAISED draw an image with a raised relief around it
4887
4888 If OVERLAPS_P is non-zero, draw only the foreground of characters
4889 and clip to the physical height of ROW.
4890
4891 Value is the x-position reached, relative to AREA of W. */
4892
4893 static int
4894 x_draw_glyphs (w, x, row, area, start, end, hl, overlaps_p)
4895 struct window *w;
4896 int x;
4897 struct glyph_row *row;
4898 enum glyph_row_area area;
4899 int start, end;
4900 enum draw_glyphs_face hl;
4901 int overlaps_p;
4902 {
4903 struct glyph_string *head, *tail;
4904 struct glyph_string *s;
4905 int last_x, area_width;
4906 int x_reached;
4907 int i, j;
4908 HDC hdc = get_frame_dc (XFRAME (WINDOW_FRAME (w)));
4909
4910 /* Let's rather be paranoid than getting a SEGV. */
4911 end = min (end, row->used[area]);
4912 start = max (0, start);
4913 start = min (end, start);
4914
4915 /* Translate X to frame coordinates. Set last_x to the right
4916 end of the drawing area. */
4917 if (row->full_width_p)
4918 {
4919 /* X is relative to the left edge of W, without scroll bars
4920 or fringes. */
4921 struct frame *f = XFRAME (WINDOW_FRAME (w));
4922 int window_left_x = WINDOW_LEFT_MARGIN (w) * CANON_X_UNIT (f);
4923
4924 x += window_left_x;
4925 area_width = XFASTINT (w->width) * CANON_X_UNIT (f);
4926 last_x = window_left_x + area_width;
4927
4928 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
4929 {
4930 int width = FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
4931 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
4932 last_x += width;
4933 else
4934 x -= width;
4935 }
4936
4937 x += FRAME_INTERNAL_BORDER_WIDTH (f);
4938 last_x -= FRAME_INTERNAL_BORDER_WIDTH (f);
4939 }
4940 else
4941 {
4942 x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, x);
4943 area_width = window_box_width (w, area);
4944 last_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, area, area_width);
4945 }
4946
4947 /* Build a doubly-linked list of glyph_string structures between
4948 head and tail from what we have to draw. Note that the macro
4949 BUILD_GLYPH_STRINGS will modify its start parameter. That's
4950 the reason we use a separate variable `i'. */
4951 i = start;
4952 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, end, head, tail, hl, x, last_x,
4953 overlaps_p);
4954 if (tail)
4955 x_reached = tail->x + tail->background_width;
4956 else
4957 x_reached = x;
4958
4959 /* If there are any glyphs with lbearing < 0 or rbearing > width in
4960 the row, redraw some glyphs in front or following the glyph
4961 strings built above. */
4962 if (head && !overlaps_p && row->contains_overlapping_glyphs_p)
4963 {
4964 int dummy_x = 0;
4965 struct glyph_string *h, *t;
4966
4967 /* Compute overhangs for all glyph strings. */
4968 for (s = head; s; s = s->next)
4969 x_compute_glyph_string_overhangs (s);
4970
4971 /* Prepend glyph strings for glyphs in front of the first glyph
4972 string that are overwritten because of the first glyph
4973 string's left overhang. The background of all strings
4974 prepended must be drawn because the first glyph string
4975 draws over it. */
4976 i = x_left_overwritten (head);
4977 if (i >= 0)
4978 {
4979 j = i;
4980 BUILD_GLYPH_STRINGS (hdc, w, row, area, j, start, h, t,
4981 DRAW_NORMAL_TEXT, dummy_x, last_x,
4982 overlaps_p);
4983 start = i;
4984 x_compute_overhangs_and_x (t, head->x, 1);
4985 x_prepend_glyph_string_lists (&head, &tail, h, t);
4986 }
4987
4988 /* Prepend glyph strings for glyphs in front of the first glyph
4989 string that overwrite that glyph string because of their
4990 right overhang. For these strings, only the foreground must
4991 be drawn, because it draws over the glyph string at `head'.
4992 The background must not be drawn because this would overwrite
4993 right overhangs of preceding glyphs for which no glyph
4994 strings exist. */
4995 i = x_left_overwriting (head);
4996 if (i >= 0)
4997 {
4998 BUILD_GLYPH_STRINGS (hdc, w, row, area, i, start, h, t,
4999 DRAW_NORMAL_TEXT, dummy_x, last_x,
5000 overlaps_p);
5001 for (s = h; s; s = s->next)
5002 s->background_filled_p = 1;
5003 x_compute_overhangs_and_x (t, head->x, 1);
5004 x_prepend_glyph_string_lists (&head, &tail, h, t);
5005 }
5006
5007 /* Append glyphs strings for glyphs following the last glyph
5008 string tail that are overwritten by tail. The background of
5009 these strings has to be drawn because tail's foreground draws
5010 over it. */
5011 i = x_right_overwritten (tail);
5012 if (i >= 0)
5013 {
5014 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
5015 DRAW_NORMAL_TEXT, x, last_x,
5016 overlaps_p);
5017 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5018 x_append_glyph_string_lists (&head, &tail, h, t);
5019 }
5020
5021 /* Append glyph strings for glyphs following the last glyph
5022 string tail that overwrite tail. The foreground of such
5023 glyphs has to be drawn because it writes into the background
5024 of tail. The background must not be drawn because it could
5025 paint over the foreground of following glyphs. */
5026 i = x_right_overwriting (tail);
5027 if (i >= 0)
5028 {
5029 BUILD_GLYPH_STRINGS (hdc, w, row, area, end, i, h, t,
5030 DRAW_NORMAL_TEXT, x, last_x,
5031 overlaps_p);
5032 for (s = h; s; s = s->next)
5033 s->background_filled_p = 1;
5034 x_compute_overhangs_and_x (h, tail->x + tail->width, 0);
5035 x_append_glyph_string_lists (&head, &tail, h, t);
5036 }
5037 }
5038
5039 /* Draw all strings. */
5040 for (s = head; s; s = s->next)
5041 x_draw_glyph_string (s);
5042
5043 if (area == TEXT_AREA
5044 && !row->full_width_p
5045 /* When drawing overlapping rows, only the glyph strings'
5046 foreground is drawn, which doesn't erase a cursor
5047 completely. */
5048 && !overlaps_p)
5049 {
5050 int x0 = head ? head->x : x;
5051 int x1 = tail ? tail->x + tail->background_width : x;
5052
5053 x0 = FRAME_TO_WINDOW_PIXEL_X (w, x0);
5054 x1 = FRAME_TO_WINDOW_PIXEL_X (w, x1);
5055
5056 if (!row->full_width_p && XFASTINT (w->left_margin_width) != 0)
5057 {
5058 int left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
5059 x0 -= left_area_width;
5060 x1 -= left_area_width;
5061 }
5062
5063 notice_overwritten_cursor (w, area, x0, x1,
5064 row->y, MATRIX_ROW_BOTTOM_Y (row));
5065 }
5066
5067 /* Value is the x-position up to which drawn, relative to AREA of W.
5068 This doesn't include parts drawn because of overhangs. */
5069 x_reached = FRAME_TO_WINDOW_PIXEL_X (w, x_reached);
5070 if (!row->full_width_p)
5071 {
5072 if (area > LEFT_MARGIN_AREA)
5073 x_reached -= window_box_width (w, LEFT_MARGIN_AREA);
5074 if (area > TEXT_AREA)
5075 x_reached -= window_box_width (w, TEXT_AREA);
5076 }
5077
5078 release_frame_dc (XFRAME (WINDOW_FRAME (w)), hdc);
5079
5080 return x_reached;
5081 }
5082
5083
5084 /* Fix the display of area AREA of overlapping row ROW in window W. */
5085
5086 static void
5087 x_fix_overlapping_area (w, row, area)
5088 struct window *w;
5089 struct glyph_row *row;
5090 enum glyph_row_area area;
5091 {
5092 int i, x;
5093
5094 BLOCK_INPUT;
5095
5096 if (area == LEFT_MARGIN_AREA)
5097 x = 0;
5098 else if (area == TEXT_AREA)
5099 x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5100 else
5101 x = (window_box_width (w, LEFT_MARGIN_AREA)
5102 + window_box_width (w, TEXT_AREA));
5103
5104 for (i = 0; i < row->used[area];)
5105 {
5106 if (row->glyphs[area][i].overlaps_vertically_p)
5107 {
5108 int start = i, start_x = x;
5109
5110 do
5111 {
5112 x += row->glyphs[area][i].pixel_width;
5113 ++i;
5114 }
5115 while (i < row->used[area]
5116 && row->glyphs[area][i].overlaps_vertically_p);
5117
5118 x_draw_glyphs (w, start_x, row, area, start, i,
5119 DRAW_NORMAL_TEXT, 1);
5120 }
5121 else
5122 {
5123 x += row->glyphs[area][i].pixel_width;
5124 ++i;
5125 }
5126 }
5127
5128 UNBLOCK_INPUT;
5129 }
5130
5131
5132 /* Output LEN glyphs starting at START at the nominal cursor position.
5133 Advance the nominal cursor over the text. The global variable
5134 updated_window contains the window being updated, updated_row is
5135 the glyph row being updated, and updated_area is the area of that
5136 row being updated. */
5137
5138 static void
5139 x_write_glyphs (start, len)
5140 struct glyph *start;
5141 int len;
5142 {
5143 int x, hpos;
5144
5145 xassert (updated_window && updated_row);
5146 BLOCK_INPUT;
5147
5148 /* Write glyphs. */
5149
5150 hpos = start - updated_row->glyphs[updated_area];
5151 x = x_draw_glyphs (updated_window, output_cursor.x,
5152 updated_row, updated_area,
5153 hpos, hpos + len,
5154 DRAW_NORMAL_TEXT, 0);
5155
5156 UNBLOCK_INPUT;
5157
5158 /* Advance the output cursor. */
5159 output_cursor.hpos += len;
5160 output_cursor.x = x;
5161 }
5162
5163
5164 /* Insert LEN glyphs from START at the nominal cursor position. */
5165
5166 static void
5167 x_insert_glyphs (start, len)
5168 struct glyph *start;
5169 register int len;
5170 {
5171 struct frame *f;
5172 struct window *w;
5173 int line_height, shift_by_width, shifted_region_width;
5174 struct glyph_row *row;
5175 struct glyph *glyph;
5176 int frame_x, frame_y, hpos;
5177 HDC hdc;
5178
5179 xassert (updated_window && updated_row);
5180 BLOCK_INPUT;
5181 w = updated_window;
5182 f = XFRAME (WINDOW_FRAME (w));
5183 hdc = get_frame_dc (f);
5184
5185 /* Get the height of the line we are in. */
5186 row = updated_row;
5187 line_height = row->height;
5188
5189 /* Get the width of the glyphs to insert. */
5190 shift_by_width = 0;
5191 for (glyph = start; glyph < start + len; ++glyph)
5192 shift_by_width += glyph->pixel_width;
5193
5194 /* Get the width of the region to shift right. */
5195 shifted_region_width = (window_box_width (w, updated_area)
5196 - output_cursor.x
5197 - shift_by_width);
5198
5199 /* Shift right. */
5200 frame_x = window_box_left (w, updated_area) + output_cursor.x;
5201 frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, output_cursor.y);
5202 BitBlt (hdc, frame_x + shift_by_width, frame_y,
5203 shifted_region_width, line_height,
5204 hdc, frame_x, frame_y, SRCCOPY);
5205
5206 /* Write the glyphs. */
5207 hpos = start - row->glyphs[updated_area];
5208 x_draw_glyphs (w, output_cursor.x, row, updated_area, hpos, hpos + len,
5209 DRAW_NORMAL_TEXT, 0);
5210
5211 /* Advance the output cursor. */
5212 output_cursor.hpos += len;
5213 output_cursor.x += shift_by_width;
5214 release_frame_dc (f, hdc);
5215
5216 UNBLOCK_INPUT;
5217 }
5218
5219
5220 /* Delete N glyphs at the nominal cursor position. Not implemented
5221 for X frames. */
5222
5223 static void
5224 x_delete_glyphs (n)
5225 register int n;
5226 {
5227 struct frame *f;
5228
5229 if (updating_frame)
5230 f = updating_frame;
5231 else
5232 f = SELECTED_FRAME ();
5233
5234 if (! FRAME_W32_P (f))
5235 return;
5236
5237 abort ();
5238 }
5239
5240
5241 /* Erase the current text line from the nominal cursor position
5242 (inclusive) to pixel column TO_X (exclusive). The idea is that
5243 everything from TO_X onward is already erased.
5244
5245 TO_X is a pixel position relative to updated_area of
5246 updated_window. TO_X == -1 means clear to the end of this area. */
5247
5248 static void
5249 x_clear_end_of_line (to_x)
5250 int to_x;
5251 {
5252 struct frame *f;
5253 struct window *w = updated_window;
5254 int max_x, min_y, max_y;
5255 int from_x, from_y, to_y;
5256
5257 xassert (updated_window && updated_row);
5258 f = XFRAME (w->frame);
5259
5260 if (updated_row->full_width_p)
5261 {
5262 max_x = XFASTINT (w->width) * CANON_X_UNIT (f);
5263 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f)
5264 && !w->pseudo_window_p)
5265 max_x += FRAME_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
5266 }
5267 else
5268 max_x = window_box_width (w, updated_area);
5269 max_y = window_text_bottom_y (w);
5270
5271 /* TO_X == 0 means don't do anything. TO_X < 0 means clear to end
5272 of window. For TO_X > 0, truncate to end of drawing area. */
5273 if (to_x == 0)
5274 return;
5275 else if (to_x < 0)
5276 to_x = max_x;
5277 else
5278 to_x = min (to_x, max_x);
5279
5280 to_y = min (max_y, output_cursor.y + updated_row->height);
5281
5282 /* Notice if the cursor will be cleared by this operation. */
5283 if (!updated_row->full_width_p)
5284 notice_overwritten_cursor (w, updated_area,
5285 output_cursor.x, -1,
5286 updated_row->y,
5287 MATRIX_ROW_BOTTOM_Y (updated_row));
5288
5289 from_x = output_cursor.x;
5290
5291 /* Translate to frame coordinates. */
5292 if (updated_row->full_width_p)
5293 {
5294 from_x = WINDOW_TO_FRAME_PIXEL_X (w, from_x);
5295 to_x = WINDOW_TO_FRAME_PIXEL_X (w, to_x);
5296 }
5297 else
5298 {
5299 from_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, from_x);
5300 to_x = WINDOW_AREA_TO_FRAME_PIXEL_X (w, updated_area, to_x);
5301 }
5302
5303 min_y = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
5304 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, max (min_y, output_cursor.y));
5305 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, to_y);
5306
5307 /* Prevent inadvertently clearing to end of the X window. */
5308 if (to_x > from_x && to_y > from_y)
5309 {
5310 HDC hdc;
5311 BLOCK_INPUT;
5312 hdc = get_frame_dc (f);
5313
5314 w32_clear_area (f, hdc, from_x, from_y, to_x - from_x, to_y - from_y);
5315 release_frame_dc (f, hdc);
5316 UNBLOCK_INPUT;
5317 }
5318 }
5319
5320
5321 /* Clear entire frame. If updating_frame is non-null, clear that
5322 frame. Otherwise clear the selected frame. */
5323
5324 static void
5325 x_clear_frame ()
5326 {
5327 struct frame *f;
5328
5329 if (updating_frame)
5330 f = updating_frame;
5331 else
5332 f = SELECTED_FRAME ();
5333
5334 if (! FRAME_W32_P (f))
5335 return;
5336
5337 /* Clearing the frame will erase any cursor, so mark them all as no
5338 longer visible. */
5339 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
5340 output_cursor.hpos = output_cursor.vpos = 0;
5341 output_cursor.x = -1;
5342
5343 /* We don't set the output cursor here because there will always
5344 follow an explicit cursor_to. */
5345 BLOCK_INPUT;
5346
5347 w32_clear_window (f);
5348
5349 /* We have to clear the scroll bars, too. If we have changed
5350 colors or something like that, then they should be notified. */
5351 x_scroll_bar_clear (f);
5352
5353 UNBLOCK_INPUT;
5354 }
5355
5356 \f
5357 /* Make audible bell. */
5358
5359 static void
5360 w32_ring_bell (void)
5361 {
5362 struct frame *f;
5363
5364 f = SELECTED_FRAME ();
5365
5366 BLOCK_INPUT;
5367
5368 if (FRAME_W32_P (f) && visible_bell)
5369 {
5370 int i;
5371 HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
5372
5373 for (i = 0; i < 5; i++)
5374 {
5375 FlashWindow (hwnd, TRUE);
5376 Sleep (10);
5377 }
5378 FlashWindow (hwnd, FALSE);
5379 }
5380 else
5381 w32_sys_ring_bell ();
5382
5383 UNBLOCK_INPUT;
5384 }
5385
5386 \f
5387 /* Specify how many text lines, from the top of the window,
5388 should be affected by insert-lines and delete-lines operations.
5389 This, and those operations, are used only within an update
5390 that is bounded by calls to x_update_begin and x_update_end. */
5391
5392 static void
5393 w32_set_terminal_window (n)
5394 register int n;
5395 {
5396 /* This function intentionally left blank. */
5397 }
5398 \f
5399
5400 \f
5401 /***********************************************************************
5402 Line Dance
5403 ***********************************************************************/
5404
5405 /* Perform an insert-lines or delete-lines operation, inserting N
5406 lines or deleting -N lines at vertical position VPOS. */
5407
5408 static void
5409 x_ins_del_lines (vpos, n)
5410 int vpos, n;
5411 {
5412 struct frame *f;
5413
5414 if (updating_frame)
5415 f = updating_frame;
5416 else
5417 f = SELECTED_FRAME ();
5418
5419 if (! FRAME_W32_P (f))
5420 return;
5421
5422 abort ();
5423 }
5424
5425
5426 /* Scroll part of the display as described by RUN. */
5427
5428 static void
5429 x_scroll_run (w, run)
5430 struct window *w;
5431 struct run *run;
5432 {
5433 struct frame *f = XFRAME (w->frame);
5434 int x, y, width, height, from_y, to_y, bottom_y;
5435 HDC hdc = get_frame_dc (f);
5436
5437 /* Get frame-relative bounding box of the text display area of W,
5438 without mode lines. Include in this box the left and right
5439 fringes of W. */
5440 window_box (w, -1, &x, &y, &width, &height);
5441 width += FRAME_X_FRINGE_WIDTH (f);
5442 x -= FRAME_X_LEFT_FRINGE_WIDTH (f);
5443
5444 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
5445 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
5446 bottom_y = y + height;
5447
5448 if (to_y < from_y)
5449 {
5450 /* Scrolling up. Make sure we don't copy part of the mode
5451 line at the bottom. */
5452 if (from_y + run->height > bottom_y)
5453 height = bottom_y - from_y;
5454 else
5455 height = run->height;
5456 }
5457 else
5458 {
5459 /* Scolling down. Make sure we don't copy over the mode line.
5460 at the bottom. */
5461 if (to_y + run->height > bottom_y)
5462 height = bottom_y - to_y;
5463 else
5464 height = run->height;
5465 }
5466
5467 BLOCK_INPUT;
5468
5469 /* Cursor off. Will be switched on again in x_update_window_end. */
5470 updated_window = w;
5471 x_clear_cursor (w);
5472
5473 BitBlt (hdc, x, to_y, width, height, hdc, x, from_y, SRCCOPY);
5474
5475 UNBLOCK_INPUT;
5476 release_frame_dc (f, hdc);
5477 }
5478
5479
5480 \f
5481 /***********************************************************************
5482 Exposure Events
5483 ***********************************************************************/
5484
5485 /* Redisplay an exposed area of frame F. X and Y are the upper-left
5486 corner of the exposed rectangle. W and H are width and height of
5487 the exposed area. All are pixel values. W or H zero means redraw
5488 the entire frame. */
5489
5490 static void
5491 expose_frame (f, x, y, w, h)
5492 struct frame *f;
5493 int x, y, w, h;
5494 {
5495 RECT r;
5496 int mouse_face_overwritten_p = 0;
5497
5498 TRACE ((stderr, "expose_frame "));
5499
5500 /* No need to redraw if frame will be redrawn soon. */
5501 if (FRAME_GARBAGED_P (f))
5502 {
5503 TRACE ((stderr, " garbaged\n"));
5504 return;
5505 }
5506
5507 /* If basic faces haven't been realized yet, there is no point in
5508 trying to redraw anything. This can happen when we get an expose
5509 event while Emacs is starting, e.g. by moving another window. */
5510 if (FRAME_FACE_CACHE (f) == NULL
5511 || FRAME_FACE_CACHE (f)->used < BASIC_FACE_ID_SENTINEL)
5512 {
5513 TRACE ((stderr, " no faces\n"));
5514 return;
5515 }
5516
5517 if (w == 0 || h == 0)
5518 {
5519 r.left = r.top = 0;
5520 r.right = CANON_X_UNIT (f) * f->width;
5521 r.bottom = CANON_Y_UNIT (f) * f->height;
5522 }
5523 else
5524 {
5525 r.left = x;
5526 r.top = y;
5527 r.right = x + w;
5528 r.bottom = y + h;
5529 }
5530
5531 TRACE ((stderr, "(%d, %d, %d, %d)\n", r.left, r.top, r.right, r.bottom));
5532 mouse_face_overwritten_p = expose_window_tree (XWINDOW (f->root_window), &r);
5533
5534 if (WINDOWP (f->tool_bar_window))
5535 mouse_face_overwritten_p
5536 |= expose_window (XWINDOW (f->tool_bar_window), &r);
5537
5538 /* Some window managers support a focus-follows-mouse style with
5539 delayed raising of frames. Imagine a partially obscured frame,
5540 and moving the mouse into partially obscured mouse-face on that
5541 frame. The visible part of the mouse-face will be highlighted,
5542 then the WM raises the obscured frame. With at least one WM, KDE
5543 2.1, Emacs is not getting any event for the raising of the frame
5544 (even tried with SubstructureRedirectMask), only Expose events.
5545 These expose events will draw text normally, i.e. not
5546 highlighted. Which means we must redo the highlight here.
5547 Subsume it under ``we love X''. --gerd 2001-08-15 */
5548 /* Included in Windows version because Windows most likely does not
5549 do the right thing if any third party tool offers
5550 focus-follows-mouse with delayed raise. --jason 2001-10-12 */
5551 if (mouse_face_overwritten_p && !FRAME_GARBAGED_P (f))
5552 {
5553 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
5554 if (f == dpyinfo->mouse_face_mouse_frame)
5555 {
5556 int x = dpyinfo->mouse_face_mouse_x;
5557 int y = dpyinfo->mouse_face_mouse_y;
5558 clear_mouse_face (dpyinfo);
5559 note_mouse_highlight (f, x, y);
5560 }
5561 }
5562 }
5563
5564
5565 /* Redraw (parts) of all windows in the window tree rooted at W that
5566 intersect R. R contains frame pixel coordinates. */
5567
5568 static int
5569 expose_window_tree (w, r)
5570 struct window *w;
5571 RECT *r;
5572 {
5573 struct frame *f = XFRAME (w->frame);
5574 int mouse_face_overwritten_p = 0;
5575
5576 while (w && !FRAME_GARBAGED_P (f))
5577 {
5578 if (!NILP (w->hchild))
5579 mouse_face_overwritten_p
5580 |= expose_window_tree (XWINDOW (w->hchild), r);
5581 else if (!NILP (w->vchild))
5582 mouse_face_overwritten_p
5583 |= expose_window_tree (XWINDOW (w->vchild), r);
5584 else
5585 mouse_face_overwritten_p |= expose_window (w, r);
5586
5587 w = NILP (w->next) ? NULL : XWINDOW (w->next);
5588 }
5589
5590 return mouse_face_overwritten_p;
5591 }
5592
5593
5594 /* Redraw the part of glyph row area AREA of glyph row ROW on window W
5595 which intersects rectangle R. R is in window-relative coordinates. */
5596
5597 static void
5598 expose_area (w, row, r, area)
5599 struct window *w;
5600 struct glyph_row *row;
5601 RECT *r;
5602 enum glyph_row_area area;
5603 {
5604 struct glyph *first = row->glyphs[area];
5605 struct glyph *end = row->glyphs[area] + row->used[area];
5606 struct glyph *last;
5607 int first_x, start_x, x;
5608
5609 if (area == TEXT_AREA && row->fill_line_p)
5610 /* If row extends face to end of line write the whole line. */
5611 x_draw_glyphs (w, 0, row, area,
5612 0, row->used[area],
5613 DRAW_NORMAL_TEXT, 0);
5614 else
5615 {
5616 /* Set START_X to the window-relative start position for drawing glyphs of
5617 AREA. The first glyph of the text area can be partially visible.
5618 The first glyphs of other areas cannot. */
5619 if (area == LEFT_MARGIN_AREA)
5620 start_x = 0;
5621 else if (area == TEXT_AREA)
5622 start_x = row->x + window_box_width (w, LEFT_MARGIN_AREA);
5623 else
5624 start_x = (window_box_width (w, LEFT_MARGIN_AREA)
5625 + window_box_width (w, TEXT_AREA));
5626 x = start_x;
5627
5628 /* Find the first glyph that must be redrawn. */
5629 while (first < end
5630 && x + first->pixel_width < r->left)
5631 {
5632 x += first->pixel_width;
5633 ++first;
5634 }
5635
5636 /* Find the last one. */
5637 last = first;
5638 first_x = x;
5639 while (last < end
5640 && x < r->right)
5641 {
5642 x += last->pixel_width;
5643 ++last;
5644 }
5645
5646 /* Repaint. */
5647 if (last > first)
5648 x_draw_glyphs (w, first_x - start_x, row, area,
5649 first - row->glyphs[area],
5650 last - row->glyphs[area],
5651 DRAW_NORMAL_TEXT, 0);
5652 }
5653 }
5654
5655
5656 /* Redraw the parts of the glyph row ROW on window W intersecting
5657 rectangle R. R is in window-relative coordinates. Value is
5658 non-zero if mouse face was overwritten. */
5659
5660 static int
5661 expose_line (w, row, r)
5662 struct window *w;
5663 struct glyph_row *row;
5664 RECT *r;
5665 {
5666 xassert (row->enabled_p);
5667
5668 if (row->mode_line_p || w->pseudo_window_p)
5669 x_draw_glyphs (w, 0, row, TEXT_AREA, 0, row->used[TEXT_AREA],
5670 DRAW_NORMAL_TEXT, 0);
5671 else
5672 {
5673 if (row->used[LEFT_MARGIN_AREA])
5674 expose_area (w, row, r, LEFT_MARGIN_AREA);
5675 if (row->used[TEXT_AREA])
5676 expose_area (w, row, r, TEXT_AREA);
5677 if (row->used[RIGHT_MARGIN_AREA])
5678 expose_area (w, row, r, RIGHT_MARGIN_AREA);
5679 x_draw_row_fringe_bitmaps (w, row);
5680 }
5681
5682 return row->mouse_face_p;
5683 }
5684
5685
5686 /* Return non-zero if W's cursor intersects rectangle R. */
5687
5688 static int
5689 x_phys_cursor_in_rect_p (w, r)
5690 struct window *w;
5691 RECT *r;
5692 {
5693 RECT cr, result;
5694 struct glyph *cursor_glyph;
5695
5696 cursor_glyph = get_phys_cursor_glyph (w);
5697 if (cursor_glyph)
5698 {
5699 cr.left = w->phys_cursor.x;
5700 cr.top = w->phys_cursor.y;
5701 cr.right = cr.left + cursor_glyph->pixel_width;
5702 cr.bottom = cr.top + w->phys_cursor_height;
5703 return IntersectRect (&result, &cr, r);
5704 }
5705 else
5706 return 0;
5707 }
5708
5709
5710 /* Redraw the part of window W intersection rectagle FR. Pixel
5711 coordinates in FR are frame relative. Call this function with
5712 input blocked. Value is non-zero if the exposure overwrites
5713 mouse-face. */
5714
5715 static int
5716 expose_window (w, fr)
5717 struct window *w;
5718 RECT *fr;
5719 {
5720 struct frame *f = XFRAME (w->frame);
5721 RECT wr, r;
5722 int mouse_face_overwritten_p = 0;
5723
5724 /* If window is not yet fully initialized, do nothing. This can
5725 happen when toolkit scroll bars are used and a window is split.
5726 Reconfiguring the scroll bar will generate an expose for a newly
5727 created window. */
5728 if (w->current_matrix == NULL)
5729 return 0;
5730
5731 /* When we're currently updating the window, display and current
5732 matrix usually don't agree. Arrange for a thorough display
5733 later. */
5734 if (w == updated_window)
5735 {
5736 SET_FRAME_GARBAGED (f);
5737 return 0;
5738 }
5739
5740 /* Frame-relative pixel rectangle of W. */
5741 wr.left = XFASTINT (w->left) * CANON_X_UNIT (f);
5742 wr.top = XFASTINT (w->top) * CANON_Y_UNIT (f);
5743 wr.right = wr.left + XFASTINT (w->width) * CANON_X_UNIT (f);
5744 wr.bottom = wr.top + XFASTINT (w->height) * CANON_Y_UNIT (f);
5745
5746 if (IntersectRect(&r, fr, &wr))
5747 {
5748 int yb = window_text_bottom_y (w);
5749 struct glyph_row *row;
5750 int cursor_cleared_p;
5751
5752 TRACE ((stderr, "expose_window (%d, %d, %d, %d)\n",
5753 r.left, r.top, r.right, r.bottom));
5754
5755 /* Convert to window coordinates. */
5756 r.left = FRAME_TO_WINDOW_PIXEL_X (w, r.left);
5757 r.right = FRAME_TO_WINDOW_PIXEL_X (w, r.right);
5758 r.top = FRAME_TO_WINDOW_PIXEL_Y (w, r.top);
5759 r.bottom = FRAME_TO_WINDOW_PIXEL_Y (w, r.bottom);
5760
5761 /* Turn off the cursor. */
5762 if (!w->pseudo_window_p
5763 && x_phys_cursor_in_rect_p (w, &r))
5764 {
5765 x_clear_cursor (w);
5766 cursor_cleared_p = 1;
5767 }
5768 else
5769 cursor_cleared_p = 0;
5770
5771 /* Find the first row intersecting the rectangle R. */
5772 for (row = w->current_matrix->rows;
5773 row->enabled_p;
5774 ++row)
5775 {
5776 int y0 = row->y;
5777 int y1 = MATRIX_ROW_BOTTOM_Y (row);
5778
5779 if ((y0 >= r.top && y0 < r.bottom)
5780 || (y1 > r.top && y1 < r.bottom)
5781 || (r.top >= y0 && r.top < y1)
5782 || (r.bottom > y0 && r.bottom < y1))
5783 {
5784 if (expose_line (w, row, &r))
5785 mouse_face_overwritten_p = 1;
5786 }
5787
5788 if (y1 >= yb)
5789 break;
5790 }
5791
5792 /* Display the mode line if there is one. */
5793 if (WINDOW_WANTS_MODELINE_P (w)
5794 && (row = MATRIX_MODE_LINE_ROW (w->current_matrix),
5795 row->enabled_p)
5796 && row->y < r.bottom)
5797 {
5798 if (expose_line (w, row, &r))
5799 mouse_face_overwritten_p = 1;
5800 }
5801
5802 if (!w->pseudo_window_p)
5803 {
5804 /* Draw border between windows. */
5805 x_draw_vertical_border (w);
5806
5807 /* Turn the cursor on again. */
5808 if (cursor_cleared_p)
5809 x_update_window_cursor (w, 1);
5810 }
5811 }
5812
5813 return mouse_face_overwritten_p;
5814 }
5815
5816 \f
5817 static void
5818 frame_highlight (f)
5819 struct frame *f;
5820 {
5821 x_update_cursor (f, 1);
5822 }
5823
5824 static void
5825 frame_unhighlight (f)
5826 struct frame *f;
5827 {
5828 x_update_cursor (f, 1);
5829 }
5830
5831 /* The focus has changed. Update the frames as necessary to reflect
5832 the new situation. Note that we can't change the selected frame
5833 here, because the Lisp code we are interrupting might become confused.
5834 Each event gets marked with the frame in which it occurred, so the
5835 Lisp code can tell when the switch took place by examining the events. */
5836
5837 static void
5838 x_new_focus_frame (dpyinfo, frame)
5839 struct w32_display_info *dpyinfo;
5840 struct frame *frame;
5841 {
5842 struct frame *old_focus = dpyinfo->w32_focus_frame;
5843
5844 if (frame != dpyinfo->w32_focus_frame)
5845 {
5846 /* Set this before calling other routines, so that they see
5847 the correct value of w32_focus_frame. */
5848 dpyinfo->w32_focus_frame = frame;
5849
5850 if (old_focus && old_focus->auto_lower)
5851 x_lower_frame (old_focus);
5852
5853 if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
5854 pending_autoraise_frame = dpyinfo->w32_focus_frame;
5855 else
5856 pending_autoraise_frame = 0;
5857 }
5858
5859 x_frame_rehighlight (dpyinfo);
5860 }
5861
5862 /* Handle an event saying the mouse has moved out of an Emacs frame. */
5863
5864 void
5865 x_mouse_leave (dpyinfo)
5866 struct w32_display_info *dpyinfo;
5867 {
5868 x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
5869 }
5870
5871 /* The focus has changed, or we have redirected a frame's focus to
5872 another frame (this happens when a frame uses a surrogate
5873 mini-buffer frame). Shift the highlight as appropriate.
5874
5875 The FRAME argument doesn't necessarily have anything to do with which
5876 frame is being highlighted or un-highlighted; we only use it to find
5877 the appropriate X display info. */
5878
5879 static void
5880 w32_frame_rehighlight (frame)
5881 struct frame *frame;
5882 {
5883 if (! FRAME_W32_P (frame))
5884 return;
5885 x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
5886 }
5887
5888 static void
5889 x_frame_rehighlight (dpyinfo)
5890 struct w32_display_info *dpyinfo;
5891 {
5892 struct frame *old_highlight = dpyinfo->w32_highlight_frame;
5893
5894 if (dpyinfo->w32_focus_frame)
5895 {
5896 dpyinfo->w32_highlight_frame
5897 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
5898 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
5899 : dpyinfo->w32_focus_frame);
5900 if (! FRAME_LIVE_P (dpyinfo->w32_highlight_frame))
5901 {
5902 FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
5903 dpyinfo->w32_highlight_frame = dpyinfo->w32_focus_frame;
5904 }
5905 }
5906 else
5907 dpyinfo->w32_highlight_frame = 0;
5908
5909 if (dpyinfo->w32_highlight_frame != old_highlight)
5910 {
5911 if (old_highlight)
5912 frame_unhighlight (old_highlight);
5913 if (dpyinfo->w32_highlight_frame)
5914 frame_highlight (dpyinfo->w32_highlight_frame);
5915 }
5916 }
5917 \f
5918 /* Keyboard processing - modifier keys, etc. */
5919
5920 /* Convert a keysym to its name. */
5921
5922 char *
5923 x_get_keysym_name (keysym)
5924 int keysym;
5925 {
5926 /* Make static so we can always return it */
5927 static char value[100];
5928
5929 BLOCK_INPUT;
5930 GetKeyNameText (keysym, value, 100);
5931 UNBLOCK_INPUT;
5932
5933 return value;
5934 }
5935
5936
5937 \f
5938 /* Mouse clicks and mouse movement. Rah. */
5939
5940 /* Given a pixel position (PIX_X, PIX_Y) on frame F, return glyph
5941 co-ordinates in (*X, *Y). Set *BOUNDS to the rectangle that the
5942 glyph at X, Y occupies, if BOUNDS != 0. If NOCLIP is non-zero, do
5943 not force the value into range. */
5944
5945 void
5946 pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
5947 FRAME_PTR f;
5948 register int pix_x, pix_y;
5949 register int *x, *y;
5950 RECT *bounds;
5951 int noclip;
5952 {
5953 /* Support tty mode: if Vwindow_system is nil, behave correctly. */
5954 if (NILP (Vwindow_system))
5955 {
5956 *x = pix_x;
5957 *y = pix_y;
5958 return;
5959 }
5960
5961 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to round down
5962 even for negative values. */
5963 if (pix_x < 0)
5964 pix_x -= FONT_WIDTH (FRAME_FONT (f)) - 1;
5965 if (pix_y < 0)
5966 pix_y -= (f)->output_data.w32->line_height - 1;
5967
5968 pix_x = PIXEL_TO_CHAR_COL (f, pix_x);
5969 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y);
5970
5971 if (bounds)
5972 {
5973 bounds->left = CHAR_TO_PIXEL_COL (f, pix_x);
5974 bounds->top = CHAR_TO_PIXEL_ROW (f, pix_y);
5975 bounds->right = bounds->left + FONT_WIDTH (FRAME_FONT (f)) - 1;
5976 bounds->bottom = bounds->top + f->output_data.w32->line_height - 1;
5977 }
5978
5979 if (!noclip)
5980 {
5981 if (pix_x < 0)
5982 pix_x = 0;
5983 else if (pix_x > FRAME_WINDOW_WIDTH (f))
5984 pix_x = FRAME_WINDOW_WIDTH (f);
5985
5986 if (pix_y < 0)
5987 pix_y = 0;
5988 else if (pix_y > f->height)
5989 pix_y = f->height;
5990 }
5991
5992 *x = pix_x;
5993 *y = pix_y;
5994 }
5995
5996
5997 /* Given HPOS/VPOS in the current matrix of W, return corresponding
5998 frame-relative pixel positions in *FRAME_X and *FRAME_Y. If we
5999 can't tell the positions because W's display is not up to date,
6000 return 0. */
6001
6002 int
6003 glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y)
6004 struct window *w;
6005 int hpos, vpos;
6006 int *frame_x, *frame_y;
6007 {
6008 int success_p;
6009
6010 xassert (hpos >= 0 && hpos < w->current_matrix->matrix_w);
6011 xassert (vpos >= 0 && vpos < w->current_matrix->matrix_h);
6012
6013 if (display_completed)
6014 {
6015 struct glyph_row *row = MATRIX_ROW (w->current_matrix, vpos);
6016 struct glyph *glyph = row->glyphs[TEXT_AREA];
6017 struct glyph *end = glyph + min (hpos, row->used[TEXT_AREA]);
6018
6019 *frame_y = row->y;
6020 *frame_x = row->x;
6021 while (glyph < end)
6022 {
6023 *frame_x += glyph->pixel_width;
6024 ++glyph;
6025 }
6026
6027 success_p = 1;
6028 }
6029 else
6030 {
6031 *frame_y = *frame_x = 0;
6032 success_p = 0;
6033 }
6034
6035 *frame_y = WINDOW_TO_FRAME_PIXEL_Y (w, *frame_y);
6036 *frame_x = WINDOW_TO_FRAME_PIXEL_X (w, *frame_x);
6037 return success_p;
6038 }
6039
6040 /* Parse a button MESSAGE. The button index is returned in PBUTTON, and
6041 the state in PUP. XBUTTON provides extra information for extended mouse
6042 button messages. Returns FALSE if unable to parse the message. */
6043 BOOL
6044 parse_button (message, xbutton, pbutton, pup)
6045 int message;
6046 int xbutton;
6047 int * pbutton;
6048 int * pup;
6049 {
6050 int button = 0;
6051 int up = 0;
6052
6053 switch (message)
6054 {
6055 case WM_LBUTTONDOWN:
6056 button = 0;
6057 up = 0;
6058 break;
6059 case WM_LBUTTONUP:
6060 button = 0;
6061 up = 1;
6062 break;
6063 case WM_MBUTTONDOWN:
6064 if (NILP (Vw32_swap_mouse_buttons))
6065 button = 1;
6066 else
6067 button = 2;
6068 up = 0;
6069 break;
6070 case WM_MBUTTONUP:
6071 if (NILP (Vw32_swap_mouse_buttons))
6072 button = 1;
6073 else
6074 button = 2;
6075 up = 1;
6076 break;
6077 case WM_RBUTTONDOWN:
6078 if (NILP (Vw32_swap_mouse_buttons))
6079 button = 2;
6080 else
6081 button = 1;
6082 up = 0;
6083 break;
6084 case WM_RBUTTONUP:
6085 if (NILP (Vw32_swap_mouse_buttons))
6086 button = 2;
6087 else
6088 button = 1;
6089 up = 1;
6090 break;
6091 case WM_XBUTTONDOWN:
6092 button = xbutton + 2;
6093 up = 0;
6094 break;
6095 case WM_XBUTTONUP:
6096 button = xbutton + 2;
6097 up = 1;
6098 break;
6099 default:
6100 return (FALSE);
6101 }
6102
6103 if (pup) *pup = up;
6104 if (pbutton) *pbutton = button;
6105
6106 return (TRUE);
6107 }
6108
6109
6110 /* Prepare a mouse-event in *RESULT for placement in the input queue.
6111
6112 If the event is a button press, then note that we have grabbed
6113 the mouse. */
6114
6115 static Lisp_Object
6116 construct_mouse_click (result, msg, f)
6117 struct input_event *result;
6118 W32Msg *msg;
6119 struct frame *f;
6120 {
6121 int button;
6122 int up;
6123
6124 parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
6125 &button, &up);
6126
6127 /* Make the event type no_event; we'll change that when we decide
6128 otherwise. */
6129 result->kind = mouse_click;
6130 result->code = button;
6131 result->timestamp = msg->msg.time;
6132 result->modifiers = (msg->dwModifiers
6133 | (up
6134 ? up_modifier
6135 : down_modifier));
6136
6137 XSETINT (result->x, LOWORD (msg->msg.lParam));
6138 XSETINT (result->y, HIWORD (msg->msg.lParam));
6139 XSETFRAME (result->frame_or_window, f);
6140 result->arg = Qnil;
6141 return Qnil;
6142 }
6143
6144 static Lisp_Object
6145 construct_mouse_wheel (result, msg, f)
6146 struct input_event *result;
6147 W32Msg *msg;
6148 struct frame *f;
6149 {
6150 POINT p;
6151 result->kind = mouse_wheel;
6152 result->code = (short) HIWORD (msg->msg.wParam);
6153 result->timestamp = msg->msg.time;
6154 result->modifiers = msg->dwModifiers;
6155 p.x = LOWORD (msg->msg.lParam);
6156 p.y = HIWORD (msg->msg.lParam);
6157 ScreenToClient (msg->msg.hwnd, &p);
6158 XSETINT (result->x, p.x);
6159 XSETINT (result->y, p.y);
6160 XSETFRAME (result->frame_or_window, f);
6161 result->arg = Qnil;
6162 return Qnil;
6163 }
6164
6165 static Lisp_Object
6166 construct_drag_n_drop (result, msg, f)
6167 struct input_event *result;
6168 W32Msg *msg;
6169 struct frame *f;
6170 {
6171 Lisp_Object files;
6172 Lisp_Object frame;
6173 HDROP hdrop;
6174 POINT p;
6175 WORD num_files;
6176 char *name;
6177 int i, len;
6178
6179 result->kind = drag_n_drop;
6180 result->code = 0;
6181 result->timestamp = msg->msg.time;
6182 result->modifiers = msg->dwModifiers;
6183
6184 hdrop = (HDROP) msg->msg.wParam;
6185 DragQueryPoint (hdrop, &p);
6186
6187 #if 0
6188 p.x = LOWORD (msg->msg.lParam);
6189 p.y = HIWORD (msg->msg.lParam);
6190 ScreenToClient (msg->msg.hwnd, &p);
6191 #endif
6192
6193 XSETINT (result->x, p.x);
6194 XSETINT (result->y, p.y);
6195
6196 num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
6197 files = Qnil;
6198
6199 for (i = 0; i < num_files; i++)
6200 {
6201 len = DragQueryFile (hdrop, i, NULL, 0);
6202 if (len <= 0)
6203 continue;
6204 name = alloca (len + 1);
6205 DragQueryFile (hdrop, i, name, len + 1);
6206 files = Fcons (build_string (name), files);
6207 }
6208
6209 DragFinish (hdrop);
6210
6211 XSETFRAME (frame, f);
6212 result->frame_or_window = Fcons (frame, files);
6213 result->arg = Qnil;
6214 return Qnil;
6215 }
6216
6217 \f
6218 /* Function to report a mouse movement to the mainstream Emacs code.
6219 The input handler calls this.
6220
6221 We have received a mouse movement event, which is given in *event.
6222 If the mouse is over a different glyph than it was last time, tell
6223 the mainstream emacs code by setting mouse_moved. If not, ask for
6224 another motion event, so we can check again the next time it moves. */
6225
6226 static MSG last_mouse_motion_event;
6227 static Lisp_Object last_mouse_motion_frame;
6228
6229 static void remember_mouse_glyph P_ ((struct frame *, int, int));
6230
6231 static void
6232 note_mouse_movement (frame, msg)
6233 FRAME_PTR frame;
6234 MSG *msg;
6235 {
6236 int mouse_x = LOWORD (msg->lParam);
6237 int mouse_y = HIWORD (msg->lParam);
6238
6239 last_mouse_movement_time = msg->time;
6240 memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
6241 XSETFRAME (last_mouse_motion_frame, frame);
6242
6243 if (msg->hwnd != FRAME_W32_WINDOW (frame))
6244 {
6245 frame->mouse_moved = 1;
6246 last_mouse_scroll_bar = Qnil;
6247 note_mouse_highlight (frame, -1, -1);
6248 }
6249
6250 /* Has the mouse moved off the glyph it was on at the last sighting? */
6251 else if (mouse_x < last_mouse_glyph.left
6252 || mouse_x > last_mouse_glyph.right
6253 || mouse_y < last_mouse_glyph.top
6254 || mouse_y > last_mouse_glyph.bottom)
6255 {
6256 frame->mouse_moved = 1;
6257 last_mouse_scroll_bar = Qnil;
6258 note_mouse_highlight (frame, mouse_x, mouse_y);
6259 /* Remember the mouse position here, as w32_mouse_position only
6260 gets called when mouse tracking is enabled but we also need
6261 to keep track of the mouse for help_echo and highlighting at
6262 other times. */
6263 remember_mouse_glyph (frame, mouse_x, mouse_y);
6264 }
6265 }
6266
6267 /* This is used for debugging, to turn off note_mouse_highlight. */
6268
6269 int disable_mouse_highlight;
6270
6271
6272 \f
6273 /************************************************************************
6274 Mouse Face
6275 ************************************************************************/
6276
6277 /* Find the glyph under window-relative coordinates X/Y in window W.
6278 Consider only glyphs from buffer text, i.e. no glyphs from overlay
6279 strings. Return in *HPOS and *VPOS the row and column number of
6280 the glyph found. Return in *AREA the glyph area containing X.
6281 Value is a pointer to the glyph found or null if X/Y is not on
6282 text, or we can't tell because W's current matrix is not up to
6283 date. */
6284
6285 static struct glyph *
6286 x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p)
6287 struct window *w;
6288 int x, y;
6289 int *hpos, *vpos, *area;
6290 int buffer_only_p;
6291 {
6292 struct glyph *glyph, *end;
6293 struct glyph_row *row = NULL;
6294 int x0, i, left_area_width;
6295
6296 /* Find row containing Y. Give up if some row is not enabled. */
6297 for (i = 0; i < w->current_matrix->nrows; ++i)
6298 {
6299 row = MATRIX_ROW (w->current_matrix, i);
6300 if (!row->enabled_p)
6301 return NULL;
6302 if (y >= row->y && y < MATRIX_ROW_BOTTOM_Y (row))
6303 break;
6304 }
6305
6306 *vpos = i;
6307 *hpos = 0;
6308
6309 /* Give up if Y is not in the window. */
6310 if (i == w->current_matrix->nrows)
6311 return NULL;
6312
6313 /* Get the glyph area containing X. */
6314 if (w->pseudo_window_p)
6315 {
6316 *area = TEXT_AREA;
6317 x0 = 0;
6318 }
6319 else
6320 {
6321 left_area_width = window_box_width (w, LEFT_MARGIN_AREA);
6322 if (x < left_area_width)
6323 {
6324 *area = LEFT_MARGIN_AREA;
6325 x0 = 0;
6326 }
6327 else if (x < left_area_width + window_box_width (w, TEXT_AREA))
6328 {
6329 *area = TEXT_AREA;
6330 x0 = row->x + left_area_width;
6331 }
6332 else
6333 {
6334 *area = RIGHT_MARGIN_AREA;
6335 x0 = left_area_width + window_box_width (w, TEXT_AREA);
6336 }
6337 }
6338
6339 /* Find glyph containing X. */
6340 glyph = row->glyphs[*area];
6341 end = glyph + row->used[*area];
6342 while (glyph < end)
6343 {
6344 if (x < x0 + glyph->pixel_width)
6345 {
6346 if (w->pseudo_window_p)
6347 break;
6348 else if (!buffer_only_p || BUFFERP (glyph->object))
6349 break;
6350 }
6351
6352 x0 += glyph->pixel_width;
6353 ++glyph;
6354 }
6355
6356 if (glyph == end)
6357 return NULL;
6358
6359 *hpos = glyph - row->glyphs[*area];
6360 return glyph;
6361 }
6362
6363
6364 /* Convert frame-relative x/y to coordinates relative to window W.
6365 Takes pseudo-windows into account. */
6366
6367 static void
6368 frame_to_window_pixel_xy (w, x, y)
6369 struct window *w;
6370 int *x, *y;
6371 {
6372 if (w->pseudo_window_p)
6373 {
6374 /* A pseudo-window is always full-width, and starts at the
6375 left edge of the frame, plus a frame border. */
6376 struct frame *f = XFRAME (w->frame);
6377 *x -= FRAME_INTERNAL_BORDER_WIDTH_SAFE (f);
6378 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6379 }
6380 else
6381 {
6382 *x = FRAME_TO_WINDOW_PIXEL_X (w, *x);
6383 *y = FRAME_TO_WINDOW_PIXEL_Y (w, *y);
6384 }
6385 }
6386
6387
6388 /* Take proper action when mouse has moved to the mode or header line of
6389 window W, x-position X. MODE_LINE_P non-zero means mouse is on the
6390 mode line. X is relative to the start of the text display area of
6391 W, so the width of fringes and scroll bars must be subtracted
6392 to get a position relative to the start of the mode line. */
6393
6394 static void
6395 note_mode_line_highlight (w, x, mode_line_p)
6396 struct window *w;
6397 int x, mode_line_p;
6398 {
6399 struct frame *f = XFRAME (w->frame);
6400 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6401 Cursor cursor = dpyinfo->vertical_scroll_bar_cursor;
6402 struct glyph_row *row;
6403
6404 if (mode_line_p)
6405 row = MATRIX_MODE_LINE_ROW (w->current_matrix);
6406 else
6407 row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
6408
6409 if (row->enabled_p)
6410 {
6411 struct glyph *glyph, *end;
6412 Lisp_Object help, map;
6413 int x0;
6414
6415 /* Find the glyph under X. */
6416 glyph = row->glyphs[TEXT_AREA];
6417 end = glyph + row->used[TEXT_AREA];
6418 x0 = - (FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f)
6419 + FRAME_X_LEFT_FRINGE_WIDTH (f));
6420
6421 while (glyph < end
6422 && x >= x0 + glyph->pixel_width)
6423 {
6424 x0 += glyph->pixel_width;
6425 ++glyph;
6426 }
6427
6428 if (glyph < end
6429 && STRINGP (glyph->object)
6430 && XSTRING (glyph->object)->intervals
6431 && glyph->charpos >= 0
6432 && glyph->charpos < XSTRING (glyph->object)->size)
6433 {
6434 /* If we're on a string with `help-echo' text property,
6435 arrange for the help to be displayed. This is done by
6436 setting the global variable help_echo to the help string. */
6437 help = Fget_text_property (make_number (glyph->charpos),
6438 Qhelp_echo, glyph->object);
6439 if (!NILP (help))
6440 {
6441 help_echo = help;
6442 XSETWINDOW (help_echo_window, w);
6443 help_echo_object = glyph->object;
6444 help_echo_pos = glyph->charpos;
6445 }
6446
6447 /* Change the mouse pointer according to what is under X/Y. */
6448 map = Fget_text_property (make_number (glyph->charpos),
6449 Qlocal_map, glyph->object);
6450 if (KEYMAPP (map))
6451 cursor = f->output_data.w32->nontext_cursor;
6452 else
6453 {
6454 map = Fget_text_property (make_number (glyph->charpos),
6455 Qkeymap, glyph->object);
6456 if (KEYMAPP (map))
6457 cursor = f->output_data.w32->nontext_cursor;
6458 }
6459 }
6460 }
6461
6462 #if 0 /* TODO: mouse cursor */
6463 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), cursor);
6464 #endif
6465 }
6466
6467
6468 /* Take proper action when the mouse has moved to position X, Y on
6469 frame F as regards highlighting characters that have mouse-face
6470 properties. Also de-highlighting chars where the mouse was before.
6471 X and Y can be negative or out of range. */
6472
6473 static void
6474 note_mouse_highlight (f, x, y)
6475 struct frame *f;
6476 int x, y;
6477 {
6478 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6479 int portion;
6480 Lisp_Object window;
6481 struct window *w;
6482 struct buffer *b;
6483
6484 /* When a menu is active, don't highlight because this looks odd. */
6485 if (popup_activated ())
6486 return;
6487
6488 if (disable_mouse_highlight
6489 || !f->glyphs_initialized_p)
6490 return;
6491
6492 dpyinfo->mouse_face_mouse_x = x;
6493 dpyinfo->mouse_face_mouse_y = y;
6494 dpyinfo->mouse_face_mouse_frame = f;
6495
6496 if (dpyinfo->mouse_face_defer)
6497 return;
6498
6499 if (gc_in_progress)
6500 {
6501 dpyinfo->mouse_face_deferred_gc = 1;
6502 return;
6503 }
6504
6505 /* Which window is that in? */
6506 window = window_from_coordinates (f, x, y, &portion, 1);
6507
6508 /* If we were displaying active text in another window, clear that. */
6509 if (! EQ (window, dpyinfo->mouse_face_window))
6510 clear_mouse_face (dpyinfo);
6511
6512 /* Not on a window -> return. */
6513 if (!WINDOWP (window))
6514 return;
6515
6516 /* Reset help_echo. It will get recomputed below. */
6517 help_echo = Qnil;
6518
6519 /* Convert to window-relative pixel coordinates. */
6520 w = XWINDOW (window);
6521 frame_to_window_pixel_xy (w, &x, &y);
6522
6523 /* Handle tool-bar window differently since it doesn't display a
6524 buffer. */
6525 if (EQ (window, f->tool_bar_window))
6526 {
6527 note_tool_bar_highlight (f, x, y);
6528 return;
6529 }
6530
6531 /* Mouse is on the mode or header line? */
6532 if (portion == 1 || portion == 3)
6533 {
6534 note_mode_line_highlight (w, x, portion == 1);
6535 return;
6536 }
6537 #if 0 /* TODO: mouse cursor */
6538 if (portion == 2)
6539 cursor = f->output_data.x->horizontal_drag_cursor;
6540 else
6541 cursor = f->output_data.x->text_cursor;
6542 #endif
6543 /* Are we in a window whose display is up to date?
6544 And verify the buffer's text has not changed. */
6545 b = XBUFFER (w->buffer);
6546 if (/* Within text portion of the window. */
6547 portion == 0
6548 && EQ (w->window_end_valid, w->buffer)
6549 && XFASTINT (w->last_modified) == BUF_MODIFF (b)
6550 && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b))
6551 {
6552 int hpos, vpos, pos, i, area;
6553 struct glyph *glyph;
6554 Lisp_Object object;
6555 Lisp_Object mouse_face = Qnil, overlay = Qnil, position;
6556 Lisp_Object *overlay_vec = NULL;
6557 int len, noverlays;
6558 struct buffer *obuf;
6559 int obegv, ozv, same_region;
6560
6561 /* Find the glyph under X/Y. */
6562 glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0);
6563
6564 /* Clear mouse face if X/Y not over text. */
6565 if (glyph == NULL
6566 || area != TEXT_AREA
6567 || !MATRIX_ROW (w->current_matrix, vpos)->displays_text_p)
6568 {
6569 clear_mouse_face (dpyinfo);
6570 /* TODO: mouse cursor */
6571 goto set_cursor;
6572 }
6573
6574 pos = glyph->charpos;
6575 object = glyph->object;
6576 if (!STRINGP (object) && !BUFFERP (object))
6577 goto set_cursor;
6578
6579 /* If we get an out-of-range value, return now; avoid an error. */
6580 if (BUFFERP (object) && pos > BUF_Z (b))
6581 goto set_cursor;
6582
6583 /* Make the window's buffer temporarily current for
6584 overlays_at and compute_char_face. */
6585 obuf = current_buffer;
6586 current_buffer = b;
6587 obegv = BEGV;
6588 ozv = ZV;
6589 BEGV = BEG;
6590 ZV = Z;
6591
6592 /* Is this char mouse-active or does it have help-echo? */
6593 position = make_number (pos);
6594
6595 if (BUFFERP (object))
6596 {
6597 /* Put all the overlays we want in a vector in overlay_vec.
6598 Store the length in len. If there are more than 10, make
6599 enough space for all, and try again. */
6600 len = 10;
6601 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6602 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
6603 if (noverlays > len)
6604 {
6605 len = noverlays;
6606 overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
6607 noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL,0);
6608 }
6609
6610 /* Sort overlays into increasing priority order. */
6611 noverlays = sort_overlays (overlay_vec, noverlays, w);
6612 }
6613 else
6614 noverlays = 0;
6615
6616 same_region = (EQ (window, dpyinfo->mouse_face_window)
6617 && vpos >= dpyinfo->mouse_face_beg_row
6618 && vpos <= dpyinfo->mouse_face_end_row
6619 && (vpos > dpyinfo->mouse_face_beg_row
6620 || hpos >= dpyinfo->mouse_face_beg_col)
6621 && (vpos < dpyinfo->mouse_face_end_row
6622 || hpos < dpyinfo->mouse_face_end_col
6623 || dpyinfo->mouse_face_past_end));
6624
6625 /* TODO: if (same_region)
6626 mouse cursor */
6627
6628 /* Check mouse-face highlighting. */
6629 if (! same_region
6630 /* If there exists an overlay with mouse-face overlapping
6631 the one we are currently highlighting, we have to
6632 check if we enter the overlapping overlay, and then
6633 highlight that. */
6634 || (OVERLAYP (dpyinfo->mouse_face_overlay)
6635 && mouse_face_overlay_overlaps (dpyinfo->mouse_face_overlay)))
6636 {
6637 /* Find the highest priority overlay that has a mouse-face
6638 property. */
6639 overlay = Qnil;
6640 for (i = noverlays - 1; i >= 0 && NILP (overlay); --i)
6641 {
6642 mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
6643 if (!NILP (mouse_face))
6644 overlay = overlay_vec[i];
6645 }
6646
6647 /* If we're actually highlighting the same overlay as
6648 before, there's no need to do that again. */
6649 if (!NILP (overlay)
6650 && EQ (overlay, dpyinfo->mouse_face_overlay))
6651 goto check_help_echo;
6652
6653 dpyinfo->mouse_face_overlay = overlay;
6654
6655 /* Clear the display of the old active region, if any. */
6656 clear_mouse_face (dpyinfo);
6657 /* TODO: mouse cursor changes. */
6658
6659 /* If no overlay applies, get a text property. */
6660 if (NILP (overlay))
6661 mouse_face = Fget_text_property (position, Qmouse_face, object);
6662
6663 /* Handle the overlay case. */
6664 if (!NILP (overlay))
6665 {
6666 /* Find the range of text around this char that
6667 should be active. */
6668 Lisp_Object before, after;
6669 int ignore;
6670
6671 before = Foverlay_start (overlay);
6672 after = Foverlay_end (overlay);
6673 /* Record this as the current active region. */
6674 fast_find_position (w, XFASTINT (before),
6675 &dpyinfo->mouse_face_beg_col,
6676 &dpyinfo->mouse_face_beg_row,
6677 &dpyinfo->mouse_face_beg_x,
6678 &dpyinfo->mouse_face_beg_y, Qnil);
6679
6680 dpyinfo->mouse_face_past_end
6681 = !fast_find_position (w, XFASTINT (after),
6682 &dpyinfo->mouse_face_end_col,
6683 &dpyinfo->mouse_face_end_row,
6684 &dpyinfo->mouse_face_end_x,
6685 &dpyinfo->mouse_face_end_y, Qnil);
6686 dpyinfo->mouse_face_window = window;
6687
6688 dpyinfo->mouse_face_face_id
6689 = face_at_buffer_position (w, pos, 0, 0,
6690 &ignore, pos + 1, 1);
6691
6692 /* Display it as active. */
6693 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6694 /* TODO: mouse cursor changes. */
6695 }
6696 /* Handle the text property case. */
6697 else if (! NILP (mouse_face) && BUFFERP (object))
6698 {
6699 /* Find the range of text around this char that
6700 should be active. */
6701 Lisp_Object before, after, beginning, end;
6702 int ignore;
6703
6704 beginning = Fmarker_position (w->start);
6705 end = make_number (BUF_Z (XBUFFER (object))
6706 - XFASTINT (w->window_end_pos));
6707 before
6708 = Fprevious_single_property_change (make_number (pos + 1),
6709 Qmouse_face,
6710 object, beginning);
6711 after
6712 = Fnext_single_property_change (position, Qmouse_face,
6713 object, end);
6714
6715 /* Record this as the current active region. */
6716 fast_find_position (w, XFASTINT (before),
6717 &dpyinfo->mouse_face_beg_col,
6718 &dpyinfo->mouse_face_beg_row,
6719 &dpyinfo->mouse_face_beg_x,
6720 &dpyinfo->mouse_face_beg_y, Qnil);
6721 dpyinfo->mouse_face_past_end
6722 = !fast_find_position (w, XFASTINT (after),
6723 &dpyinfo->mouse_face_end_col,
6724 &dpyinfo->mouse_face_end_row,
6725 &dpyinfo->mouse_face_end_x,
6726 &dpyinfo->mouse_face_end_y, Qnil);
6727 dpyinfo->mouse_face_window = window;
6728
6729 if (BUFFERP (object))
6730 dpyinfo->mouse_face_face_id
6731 = face_at_buffer_position (w, pos, 0, 0,
6732 &ignore, pos + 1, 1);
6733
6734 /* Display it as active. */
6735 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6736 /* TODO: mouse cursor changes. */
6737 }
6738 else if (!NILP (mouse_face) && STRINGP (object))
6739 {
6740 Lisp_Object b, e;
6741 int ignore;
6742
6743 b = Fprevious_single_property_change (make_number (pos + 1),
6744 Qmouse_face,
6745 object, Qnil);
6746 e = Fnext_single_property_change (position, Qmouse_face,
6747 object, Qnil);
6748 if (NILP (b))
6749 b = make_number (0);
6750 if (NILP (e))
6751 e = make_number (XSTRING (object)->size - 1);
6752 fast_find_string_pos (w, XINT (b), object,
6753 &dpyinfo->mouse_face_beg_col,
6754 &dpyinfo->mouse_face_beg_row,
6755 &dpyinfo->mouse_face_beg_x,
6756 &dpyinfo->mouse_face_beg_y, 0);
6757 fast_find_string_pos (w, XINT (e), object,
6758 &dpyinfo->mouse_face_end_col,
6759 &dpyinfo->mouse_face_end_row,
6760 &dpyinfo->mouse_face_end_x,
6761 &dpyinfo->mouse_face_end_y, 1);
6762 dpyinfo->mouse_face_past_end = 0;
6763 dpyinfo->mouse_face_window = window;
6764 dpyinfo->mouse_face_face_id
6765 = face_at_string_position (w, object, pos, 0, 0, 0, &ignore,
6766 glyph->face_id, 1);
6767 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6768 /* TODO: mouse cursor changes. */
6769 }
6770 else if (STRINGP (object) && NILP (mouse_face))
6771 {
6772 /* A string which doesn't have mouse-face, but
6773 the text ``under'' it might have. */
6774 struct glyph_row *r = MATRIX_ROW (w->current_matrix, vpos);
6775 int start = MATRIX_ROW_START_CHARPOS (r);
6776
6777 pos = string_buffer_position (w, object, start);
6778 if (pos > 0)
6779 mouse_face = get_char_property_and_overlay (make_number (pos),
6780 Qmouse_face,
6781 w->buffer,
6782 &overlay);
6783 if (!NILP (mouse_face) && !NILP (overlay))
6784 {
6785 Lisp_Object before = Foverlay_start (overlay);
6786 Lisp_Object after = Foverlay_end (overlay);
6787 int ignore;
6788
6789 /* Note that we might not be able to find position
6790 BEFORE in the glyph matrix if the overlay is
6791 entirely covered by a `display' property. In
6792 this case, we overshoot. So let's stop in
6793 the glyph matrix before glyphs for OBJECT. */
6794 fast_find_position (w, XFASTINT (before),
6795 &dpyinfo->mouse_face_beg_col,
6796 &dpyinfo->mouse_face_beg_row,
6797 &dpyinfo->mouse_face_beg_x,
6798 &dpyinfo->mouse_face_beg_y,
6799 object);
6800
6801 dpyinfo->mouse_face_past_end
6802 = !fast_find_position (w, XFASTINT (after),
6803 &dpyinfo->mouse_face_end_col,
6804 &dpyinfo->mouse_face_end_row,
6805 &dpyinfo->mouse_face_end_x,
6806 &dpyinfo->mouse_face_end_y,
6807 Qnil);
6808 dpyinfo->mouse_face_window = window;
6809 dpyinfo->mouse_face_face_id
6810 = face_at_buffer_position (w, pos, 0, 0,
6811 &ignore, pos + 1, 1);
6812
6813 /* Display it as active. */
6814 show_mouse_face (dpyinfo, DRAW_MOUSE_FACE);
6815 /* TODO: mouse cursor changes. */
6816 }
6817 }
6818 }
6819
6820 check_help_echo:
6821
6822 /* Look for a `help-echo' property. */
6823 {
6824 Lisp_Object help, overlay;
6825
6826 /* Check overlays first. */
6827 help = overlay = Qnil;
6828 for (i = noverlays - 1; i >= 0 && NILP (help); --i)
6829 {
6830 overlay = overlay_vec[i];
6831 help = Foverlay_get (overlay, Qhelp_echo);
6832 }
6833
6834 if (!NILP (help))
6835 {
6836 help_echo = help;
6837 help_echo_window = window;
6838 help_echo_object = overlay;
6839 help_echo_pos = pos;
6840 }
6841 else
6842 {
6843 Lisp_Object object = glyph->object;
6844 int charpos = glyph->charpos;
6845
6846 /* Try text properties. */
6847 if (STRINGP (object)
6848 && charpos >= 0
6849 && charpos < XSTRING (object)->size)
6850 {
6851 help = Fget_text_property (make_number (charpos),
6852 Qhelp_echo, object);
6853 if (NILP (help))
6854 {
6855 /* If the string itself doesn't specify a help-echo,
6856 see if the buffer text ``under'' it does. */
6857 struct glyph_row *r
6858 = MATRIX_ROW (w->current_matrix, vpos);
6859 int start = MATRIX_ROW_START_CHARPOS (r);
6860 int pos = string_buffer_position (w, object, start);
6861 if (pos > 0)
6862 {
6863 help = Fget_char_property (make_number (pos),
6864 Qhelp_echo, w->buffer);
6865 if (!NILP (help))
6866 {
6867 charpos = pos;
6868 object = w->buffer;
6869 }
6870 }
6871 }
6872 }
6873 else if (BUFFERP (object)
6874 && charpos >= BEGV
6875 && charpos < ZV)
6876 help = Fget_text_property (make_number (charpos), Qhelp_echo,
6877 object);
6878
6879 if (!NILP (help))
6880 {
6881 help_echo = help;
6882 help_echo_window = window;
6883 help_echo_object = object;
6884 help_echo_pos = charpos;
6885 }
6886 }
6887 }
6888
6889 BEGV = obegv;
6890 ZV = ozv;
6891 current_buffer = obuf;
6892 }
6893
6894 set_cursor:
6895 /* TODO: mouse cursor changes. */
6896 ;
6897 }
6898
6899 static void
6900 redo_mouse_highlight ()
6901 {
6902 if (!NILP (last_mouse_motion_frame)
6903 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
6904 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
6905 LOWORD (last_mouse_motion_event.lParam),
6906 HIWORD (last_mouse_motion_event.lParam));
6907 }
6908
6909
6910 \f
6911 /***********************************************************************
6912 Tool-bars
6913 ***********************************************************************/
6914
6915 static int x_tool_bar_item P_ ((struct frame *, int, int,
6916 struct glyph **, int *, int *, int *));
6917
6918 /* Tool-bar item index of the item on which a mouse button was pressed
6919 or -1. */
6920
6921 static int last_tool_bar_item;
6922
6923
6924 /* Get information about the tool-bar item at position X/Y on frame F.
6925 Return in *GLYPH a pointer to the glyph of the tool-bar item in
6926 the current matrix of the tool-bar window of F, or NULL if not
6927 on a tool-bar item. Return in *PROP_IDX the index of the tool-bar
6928 item in F->tool_bar_items. Value is
6929
6930 -1 if X/Y is not on a tool-bar item
6931 0 if X/Y is on the same item that was highlighted before.
6932 1 otherwise. */
6933
6934 static int
6935 x_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx)
6936 struct frame *f;
6937 int x, y;
6938 struct glyph **glyph;
6939 int *hpos, *vpos, *prop_idx;
6940 {
6941 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6942 struct window *w = XWINDOW (f->tool_bar_window);
6943 int area;
6944
6945 /* Find the glyph under X/Y. */
6946 *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0);
6947 if (*glyph == NULL)
6948 return -1;
6949
6950 /* Get the start of this tool-bar item's properties in
6951 f->tool_bar_items. */
6952 if (!tool_bar_item_info (f, *glyph, prop_idx))
6953 return -1;
6954
6955 /* Is mouse on the highlighted item? */
6956 if (EQ (f->tool_bar_window, dpyinfo->mouse_face_window)
6957 && *vpos >= dpyinfo->mouse_face_beg_row
6958 && *vpos <= dpyinfo->mouse_face_end_row
6959 && (*vpos > dpyinfo->mouse_face_beg_row
6960 || *hpos >= dpyinfo->mouse_face_beg_col)
6961 && (*vpos < dpyinfo->mouse_face_end_row
6962 || *hpos < dpyinfo->mouse_face_end_col
6963 || dpyinfo->mouse_face_past_end))
6964 return 0;
6965
6966 return 1;
6967 }
6968
6969
6970 /* Handle mouse button event on the tool-bar of frame F, at
6971 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
6972 or ButtonRelase. */
6973
6974 static void
6975 w32_handle_tool_bar_click (f, button_event)
6976 struct frame *f;
6977 struct input_event *button_event;
6978 {
6979 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
6980 struct window *w = XWINDOW (f->tool_bar_window);
6981 int hpos, vpos, prop_idx;
6982 struct glyph *glyph;
6983 Lisp_Object enabled_p;
6984 int x = XFASTINT (button_event->x);
6985 int y = XFASTINT (button_event->y);
6986
6987 /* If not on the highlighted tool-bar item, return. */
6988 frame_to_window_pixel_xy (w, &x, &y);
6989 if (x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx) != 0)
6990 return;
6991
6992 /* If item is disabled, do nothing. */
6993 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
6994 if (NILP (enabled_p))
6995 return;
6996
6997 if (button_event->kind == mouse_click)
6998 {
6999 /* Show item in pressed state. */
7000 show_mouse_face (dpyinfo, DRAW_IMAGE_SUNKEN);
7001 dpyinfo->mouse_face_image_state = DRAW_IMAGE_SUNKEN;
7002 last_tool_bar_item = prop_idx;
7003 }
7004 else
7005 {
7006 Lisp_Object key, frame;
7007 struct input_event event;
7008
7009 /* Show item in released state. */
7010 show_mouse_face (dpyinfo, DRAW_IMAGE_RAISED);
7011 dpyinfo->mouse_face_image_state = DRAW_IMAGE_RAISED;
7012
7013 key = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_KEY);
7014
7015 XSETFRAME (frame, f);
7016 event.kind = TOOL_BAR_EVENT;
7017 event.frame_or_window = frame;
7018 event.arg = frame;
7019 kbd_buffer_store_event (&event);
7020
7021 event.kind = TOOL_BAR_EVENT;
7022 event.frame_or_window = frame;
7023 event.arg = key;
7024 event.modifiers = button_event->modifiers;
7025 kbd_buffer_store_event (&event);
7026 last_tool_bar_item = -1;
7027 }
7028 }
7029
7030
7031 /* Possibly highlight a tool-bar item on frame F when mouse moves to
7032 tool-bar window-relative coordinates X/Y. Called from
7033 note_mouse_highlight. */
7034
7035 static void
7036 note_tool_bar_highlight (f, x, y)
7037 struct frame *f;
7038 int x, y;
7039 {
7040 Lisp_Object window = f->tool_bar_window;
7041 struct window *w = XWINDOW (window);
7042 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7043 int hpos, vpos;
7044 struct glyph *glyph;
7045 struct glyph_row *row;
7046 int i;
7047 Lisp_Object enabled_p;
7048 int prop_idx;
7049 enum draw_glyphs_face draw = DRAW_IMAGE_RAISED;
7050 int mouse_down_p, rc;
7051
7052 /* Function note_mouse_highlight is called with negative x(y
7053 values when mouse moves outside of the frame. */
7054 if (x <= 0 || y <= 0)
7055 {
7056 clear_mouse_face (dpyinfo);
7057 return;
7058 }
7059
7060 rc = x_tool_bar_item (f, x, y, &glyph, &hpos, &vpos, &prop_idx);
7061 if (rc < 0)
7062 {
7063 /* Not on tool-bar item. */
7064 clear_mouse_face (dpyinfo);
7065 return;
7066 }
7067 else if (rc == 0)
7068 /* On same tool-bar item as before. */
7069 goto set_help_echo;
7070
7071 clear_mouse_face (dpyinfo);
7072
7073 /* Mouse is down, but on different tool-bar item? */
7074 mouse_down_p = (dpyinfo->grabbed
7075 && f == last_mouse_frame
7076 && FRAME_LIVE_P (f));
7077 if (mouse_down_p
7078 && last_tool_bar_item != prop_idx)
7079 return;
7080
7081 dpyinfo->mouse_face_image_state = DRAW_NORMAL_TEXT;
7082 draw = mouse_down_p ? DRAW_IMAGE_SUNKEN : DRAW_IMAGE_RAISED;
7083
7084 /* If tool-bar item is not enabled, don't highlight it. */
7085 enabled_p = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_ENABLED_P);
7086 if (!NILP (enabled_p))
7087 {
7088 /* Compute the x-position of the glyph. In front and past the
7089 image is a space. We include this is the highlighted area. */
7090 row = MATRIX_ROW (w->current_matrix, vpos);
7091 for (i = x = 0; i < hpos; ++i)
7092 x += row->glyphs[TEXT_AREA][i].pixel_width;
7093
7094 /* Record this as the current active region. */
7095 dpyinfo->mouse_face_beg_col = hpos;
7096 dpyinfo->mouse_face_beg_row = vpos;
7097 dpyinfo->mouse_face_beg_x = x;
7098 dpyinfo->mouse_face_beg_y = row->y;
7099 dpyinfo->mouse_face_past_end = 0;
7100
7101 dpyinfo->mouse_face_end_col = hpos + 1;
7102 dpyinfo->mouse_face_end_row = vpos;
7103 dpyinfo->mouse_face_end_x = x + glyph->pixel_width;
7104 dpyinfo->mouse_face_end_y = row->y;
7105 dpyinfo->mouse_face_window = window;
7106 dpyinfo->mouse_face_face_id = TOOL_BAR_FACE_ID;
7107
7108 /* Display it as active. */
7109 show_mouse_face (dpyinfo, draw);
7110 dpyinfo->mouse_face_image_state = draw;
7111 }
7112
7113 set_help_echo:
7114
7115 /* Set help_echo to a help string.to display for this tool-bar item.
7116 w32_read_socket does the rest. */
7117 help_echo_object = help_echo_window = Qnil;
7118 help_echo_pos = -1;
7119 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_HELP);
7120 if (NILP (help_echo))
7121 help_echo = AREF (f->tool_bar_items, prop_idx + TOOL_BAR_ITEM_CAPTION);
7122 }
7123
7124
7125 \f
7126 /* Find the glyph matrix position of buffer position CHARPOS in window
7127 *W. HPOS, *VPOS, *X, and *Y are set to the positions found. W's
7128 current glyphs must be up to date. If CHARPOS is above window
7129 start return (0, 0, 0, 0). If CHARPOS is after end of W, return end
7130 of last line in W. In the row containing CHARPOS, stop before glyphs
7131 having STOP as object. */
7132
7133 #if 0 /* This is a version of fast_find_position that's more correct
7134 in the presence of hscrolling, for example. I didn't install
7135 it right away because the problem fixed is minor, it failed
7136 in 20.x as well, and I think it's too risky to install
7137 so near the release of 21.1. 2001-09-25 gerd. */
7138
7139 static int
7140 fast_find_position (w, charpos, hpos, vpos, x, y, stop)
7141 struct window *w;
7142 int charpos;
7143 int *hpos, *vpos, *x, *y;
7144 Lisp_Object stop;
7145 {
7146 struct glyph_row *row, *first;
7147 struct glyph *glyph, *end;
7148 int i, past_end = 0;
7149
7150 first = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7151 row = row_containing_pos (w, charpos, first, NULL, 0);
7152 if (row == NULL)
7153 {
7154 if (charpos < MATRIX_ROW_START_CHARPOS (first))
7155 {
7156 *x = *y = *hpos = *vpos = 0;
7157 return 0;
7158 }
7159 else
7160 {
7161 row = MATRIX_ROW (w->current_matrix, XFASTINT (w->window_end_vpos));
7162 past_end = 1;
7163 }
7164 }
7165
7166 *x = row->x;
7167 *y = row->y;
7168 *vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7169
7170 glyph = row->glyphs[TEXT_AREA];
7171 end = glyph + row->used[TEXT_AREA];
7172
7173 /* Skip over glyphs not having an object at the start of the row.
7174 These are special glyphs like truncation marks on terminal
7175 frames. */
7176 if (row->displays_text_p)
7177 while (glyph < end
7178 && INTEGERP (glyph->object)
7179 && !EQ (stop, glyph->object)
7180 && glyph->charpos < 0)
7181 {
7182 *x += glyph->pixel_width;
7183 ++glyph;
7184 }
7185
7186 while (glyph < end
7187 && !INTEGERP (glyph->object)
7188 && !EQ (stop, glyph->object)
7189 && (!BUFFERP (glyph->object)
7190 || glyph->charpos < charpos))
7191 {
7192 *x += glyph->pixel_width;
7193 ++glyph;
7194 }
7195
7196 *hpos = glyph - row->glyphs[TEXT_AREA];
7197 return past_end;
7198 }
7199
7200 #else /* not 0 */
7201
7202 static int
7203 fast_find_position (w, pos, hpos, vpos, x, y, stop)
7204 struct window *w;
7205 int pos;
7206 int *hpos, *vpos, *x, *y;
7207 Lisp_Object stop;
7208 {
7209 int i;
7210 int lastcol;
7211 int maybe_next_line_p = 0;
7212 int line_start_position;
7213 int yb = window_text_bottom_y (w);
7214 struct glyph_row *row, *best_row;
7215 int row_vpos, best_row_vpos;
7216 int current_x;
7217
7218 row = best_row = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7219 row_vpos = best_row_vpos = MATRIX_ROW_VPOS (row, w->current_matrix);
7220
7221 while (row->y < yb)
7222 {
7223 if (row->used[TEXT_AREA])
7224 line_start_position = row->glyphs[TEXT_AREA]->charpos;
7225 else
7226 line_start_position = 0;
7227
7228 if (line_start_position > pos)
7229 break;
7230 /* If the position sought is the end of the buffer,
7231 don't include the blank lines at the bottom of the window. */
7232 else if (line_start_position == pos
7233 && pos == BUF_ZV (XBUFFER (w->buffer)))
7234 {
7235 maybe_next_line_p = 1;
7236 break;
7237 }
7238 else if (line_start_position > 0)
7239 {
7240 best_row = row;
7241 best_row_vpos = row_vpos;
7242 }
7243
7244 if (row->y + row->height >= yb)
7245 break;
7246
7247 ++row;
7248 ++row_vpos;
7249 }
7250
7251 /* Find the right column within BEST_ROW. */
7252 lastcol = 0;
7253 current_x = best_row->x;
7254 for (i = 0; i < best_row->used[TEXT_AREA]; i++)
7255 {
7256 struct glyph *glyph = best_row->glyphs[TEXT_AREA] + i;
7257 int charpos = glyph->charpos;
7258
7259 if (BUFFERP (glyph->object))
7260 {
7261 if (charpos == pos)
7262 {
7263 *hpos = i;
7264 *vpos = best_row_vpos;
7265 *x = current_x;
7266 *y = best_row->y;
7267 return 1;
7268 }
7269 else if (charpos > pos)
7270 break;
7271 }
7272 else if (EQ (glyph->object, stop))
7273 break;
7274
7275 if (charpos > 0)
7276 lastcol = i;
7277 current_x += glyph->pixel_width;
7278 }
7279
7280 /* If we're looking for the end of the buffer,
7281 and we didn't find it in the line we scanned,
7282 use the start of the following line. */
7283 if (maybe_next_line_p)
7284 {
7285 ++best_row;
7286 ++best_row_vpos;
7287 lastcol = 0;
7288 current_x = best_row->x;
7289 }
7290
7291 *vpos = best_row_vpos;
7292 *hpos = lastcol + 1;
7293 *x = current_x;
7294 *y = best_row->y;
7295 return 0;
7296 }
7297
7298 #endif /* not 0 */
7299
7300
7301 /* Find the position of the glyph for position POS in OBJECT in
7302 window W's current matrix, and return in *X/*Y the pixel
7303 coordinates, and return in *HPOS/*VPOS the column/row of the glyph.
7304
7305 RIGHT_P non-zero means return the position of the right edge of the
7306 glyph, RIGHT_P zero means return the left edge position.
7307
7308 If no glyph for POS exists in the matrix, return the position of
7309 the glyph with the next smaller position that is in the matrix, if
7310 RIGHT_P is zero. If RIGHT_P is non-zero, and no glyph for POS
7311 exists in the matrix, return the position of the glyph with the
7312 next larger position in OBJECT.
7313
7314 Value is non-zero if a glyph was found. */
7315
7316 static int
7317 fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p)
7318 struct window *w;
7319 int pos;
7320 Lisp_Object object;
7321 int *hpos, *vpos, *x, *y;
7322 int right_p;
7323 {
7324 int yb = window_text_bottom_y (w);
7325 struct glyph_row *r;
7326 struct glyph *best_glyph = NULL;
7327 struct glyph_row *best_row = NULL;
7328 int best_x = 0;
7329
7330 for (r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7331 r->enabled_p && r->y < yb;
7332 ++r)
7333 {
7334 struct glyph *g = r->glyphs[TEXT_AREA];
7335 struct glyph *e = g + r->used[TEXT_AREA];
7336 int gx;
7337
7338 for (gx = r->x; g < e; gx += g->pixel_width, ++g)
7339 if (EQ (g->object, object))
7340 {
7341 if (g->charpos == pos)
7342 {
7343 best_glyph = g;
7344 best_x = gx;
7345 best_row = r;
7346 goto found;
7347 }
7348 else if (best_glyph == NULL
7349 || ((abs (g->charpos - pos)
7350 < abs (best_glyph->charpos - pos))
7351 && (right_p
7352 ? g->charpos < pos
7353 : g->charpos > pos)))
7354 {
7355 best_glyph = g;
7356 best_x = gx;
7357 best_row = r;
7358 }
7359 }
7360 }
7361
7362 found:
7363
7364 if (best_glyph)
7365 {
7366 *x = best_x;
7367 *hpos = best_glyph - best_row->glyphs[TEXT_AREA];
7368
7369 if (right_p)
7370 {
7371 *x += best_glyph->pixel_width;
7372 ++*hpos;
7373 }
7374
7375 *y = best_row->y;
7376 *vpos = best_row - w->current_matrix->rows;
7377 }
7378
7379 return best_glyph != NULL;
7380 }
7381
7382
7383 /* Display the active region described by mouse_face_*
7384 in its mouse-face if HL > 0, in its normal face if HL = 0. */
7385
7386 static void
7387 show_mouse_face (dpyinfo, draw)
7388 struct w32_display_info *dpyinfo;
7389 enum draw_glyphs_face draw;
7390 {
7391 struct window *w = XWINDOW (dpyinfo->mouse_face_window);
7392 struct frame *f = XFRAME (WINDOW_FRAME (w));
7393
7394 if (/* If window is in the process of being destroyed, don't bother
7395 to do anything. */
7396 w->current_matrix != NULL
7397 /* Recognize when we are called to operate on rows that don't exist
7398 anymore. This can happen when a window is split. */
7399 && dpyinfo->mouse_face_end_row < w->current_matrix->nrows)
7400 {
7401 int phys_cursor_on_p = w->phys_cursor_on_p;
7402 struct glyph_row *row, *first, *last;
7403
7404 first = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_beg_row);
7405 last = MATRIX_ROW (w->current_matrix, dpyinfo->mouse_face_end_row);
7406
7407 for (row = first; row <= last && row->enabled_p; ++row)
7408 {
7409 int start_hpos, end_hpos, start_x;
7410
7411 /* For all but the first row, the highlight starts at column 0. */
7412 if (row == first)
7413 {
7414 start_hpos = dpyinfo->mouse_face_beg_col;
7415 start_x = dpyinfo->mouse_face_beg_x;
7416 }
7417 else
7418 {
7419 start_hpos = 0;
7420 start_x = 0;
7421 }
7422
7423 if (row == last)
7424 end_hpos = dpyinfo->mouse_face_end_col;
7425 else
7426 end_hpos = row->used[TEXT_AREA];
7427
7428 if (end_hpos > start_hpos)
7429 {
7430 x_draw_glyphs (w, start_x, row, TEXT_AREA,
7431 start_hpos, end_hpos, draw, 0);
7432
7433 row->mouse_face_p
7434 = draw == DRAW_MOUSE_FACE || draw == DRAW_IMAGE_RAISED;
7435 }
7436 }
7437
7438 /* When we've written over the cursor, arrange for it to
7439 be displayed again. */
7440 if (phys_cursor_on_p && !w->phys_cursor_on_p)
7441 x_display_cursor (w, 1,
7442 w->phys_cursor.hpos, w->phys_cursor.vpos,
7443 w->phys_cursor.x, w->phys_cursor.y);
7444 }
7445
7446 #if 0 /* TODO: mouse cursor */
7447 /* Change the mouse cursor. */
7448 if (draw == DRAW_NORMAL_TEXT)
7449 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7450 f->output_data.x->text_cursor);
7451 else if (draw == DRAW_MOUSE_FACE)
7452 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7453 f->output_data.x->cross_cursor);
7454 else
7455 XDefineCursor (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
7456 f->output_data.x->nontext_cursor);
7457 #endif
7458 }
7459
7460 /* Clear out the mouse-highlighted active region.
7461 Redraw it un-highlighted first. */
7462
7463 static int
7464 clear_mouse_face (dpyinfo)
7465 struct w32_display_info *dpyinfo;
7466 {
7467 int cleared = 0;
7468
7469 if (! NILP (dpyinfo->mouse_face_window))
7470 {
7471 show_mouse_face (dpyinfo, DRAW_NORMAL_TEXT);
7472 cleared = 1;
7473 }
7474
7475 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7476 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7477 dpyinfo->mouse_face_window = Qnil;
7478 dpyinfo->mouse_face_overlay = Qnil;
7479 return cleared;
7480 }
7481
7482
7483 /* Clear any mouse-face on window W. This function is part of the
7484 redisplay interface, and is called from try_window_id and similar
7485 functions to ensure the mouse-highlight is off. */
7486
7487 static void
7488 x_clear_mouse_face (w)
7489 struct window *w;
7490 {
7491 struct w32_display_info *dpyinfo
7492 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
7493 Lisp_Object window;
7494
7495 BLOCK_INPUT;
7496 XSETWINDOW (window, w);
7497 if (EQ (window, dpyinfo->mouse_face_window))
7498 clear_mouse_face (dpyinfo);
7499 UNBLOCK_INPUT;
7500 }
7501
7502
7503 /* Just discard the mouse face information for frame F, if any.
7504 This is used when the size of F is changed. */
7505
7506 void
7507 cancel_mouse_face (f)
7508 FRAME_PTR f;
7509 {
7510 Lisp_Object window;
7511 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
7512
7513 window = dpyinfo->mouse_face_window;
7514 if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
7515 {
7516 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
7517 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
7518 dpyinfo->mouse_face_window = Qnil;
7519 }
7520 }
7521 \f
7522 static struct scroll_bar *x_window_to_scroll_bar ();
7523 static void x_scroll_bar_report_motion ();
7524 static int glyph_rect P_ ((struct frame *f, int, int, RECT *));
7525
7526
7527 /* Try to determine frame pixel position and size of the glyph under
7528 frame pixel coordinates X/Y on frame F . Return the position and
7529 size in *RECT. Value is non-zero if we could compute these
7530 values. */
7531
7532 static int
7533 glyph_rect (f, x, y, rect)
7534 struct frame *f;
7535 int x, y;
7536 RECT *rect;
7537 {
7538 Lisp_Object window;
7539 int part, found = 0;
7540
7541 window = window_from_coordinates (f, x, y, &part, 0);
7542 if (!NILP (window))
7543 {
7544 struct window *w = XWINDOW (window);
7545 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
7546 struct glyph_row *end = r + w->current_matrix->nrows - 1;
7547
7548 frame_to_window_pixel_xy (w, &x, &y);
7549
7550 for (; !found && r < end && r->enabled_p; ++r)
7551 if (r->y + r->height >= y)
7552 {
7553 struct glyph *g = r->glyphs[TEXT_AREA];
7554 struct glyph *end = g + r->used[TEXT_AREA];
7555 int gx;
7556
7557 for (gx = r->x; !found && g < end; gx += g->pixel_width, ++g)
7558 if (gx + g->pixel_width >= x)
7559 {
7560 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
7561 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
7562 rect->right = rect->left + g->pixel_width;
7563 rect->bottom = rect->top + r->height;
7564 found = 1;
7565 }
7566 }
7567 }
7568
7569 return found;
7570 }
7571
7572 /* Record the position of the mouse in last_mouse_glyph. */
7573 static void
7574 remember_mouse_glyph (f1, gx, gy)
7575 struct frame * f1;
7576 int gx, gy;
7577 {
7578 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
7579 {
7580 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
7581 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
7582
7583 /* Arrange for the division in PIXEL_TO_CHAR_COL etc. to
7584 round down even for negative values. */
7585 if (gx < 0)
7586 gx -= width - 1;
7587 if (gy < 0)
7588 gy -= height - 1;
7589 #if 0
7590 /* This was the original code from XTmouse_position, but it seems
7591 to give the position of the glyph diagonally next to the one
7592 the mouse is over. */
7593 gx = (gx + width - 1) / width * width;
7594 gy = (gy + height - 1) / height * height;
7595 #else
7596 gx = gx / width * width;
7597 gy = gy / height * height;
7598 #endif
7599
7600 last_mouse_glyph.left = gx;
7601 last_mouse_glyph.top = gy;
7602 last_mouse_glyph.right = gx + width;
7603 last_mouse_glyph.bottom = gy + height;
7604 }
7605 }
7606
7607 /* Return the current position of the mouse.
7608 *fp should be a frame which indicates which display to ask about.
7609
7610 If the mouse movement started in a scroll bar, set *fp, *bar_window,
7611 and *part to the frame, window, and scroll bar part that the mouse
7612 is over. Set *x and *y to the portion and whole of the mouse's
7613 position on the scroll bar.
7614
7615 If the mouse movement started elsewhere, set *fp to the frame the
7616 mouse is on, *bar_window to nil, and *x and *y to the character cell
7617 the mouse is over.
7618
7619 Set *time to the server time-stamp for the time at which the mouse
7620 was at this position.
7621
7622 Don't store anything if we don't have a valid set of values to report.
7623
7624 This clears the mouse_moved flag, so we can wait for the next mouse
7625 movement. */
7626
7627 static void
7628 w32_mouse_position (fp, insist, bar_window, part, x, y, time)
7629 FRAME_PTR *fp;
7630 int insist;
7631 Lisp_Object *bar_window;
7632 enum scroll_bar_part *part;
7633 Lisp_Object *x, *y;
7634 unsigned long *time;
7635 {
7636 FRAME_PTR f1;
7637
7638 BLOCK_INPUT;
7639
7640 if (! NILP (last_mouse_scroll_bar) && insist == 0)
7641 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
7642 else
7643 {
7644 POINT pt;
7645
7646 Lisp_Object frame, tail;
7647
7648 /* Clear the mouse-moved flag for every frame on this display. */
7649 FOR_EACH_FRAME (tail, frame)
7650 XFRAME (frame)->mouse_moved = 0;
7651
7652 last_mouse_scroll_bar = Qnil;
7653
7654 GetCursorPos (&pt);
7655
7656 /* Now we have a position on the root; find the innermost window
7657 containing the pointer. */
7658 {
7659 if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
7660 && FRAME_LIVE_P (last_mouse_frame))
7661 {
7662 /* If mouse was grabbed on a frame, give coords for that frame
7663 even if the mouse is now outside it. */
7664 f1 = last_mouse_frame;
7665 }
7666 else
7667 {
7668 /* Is window under mouse one of our frames? */
7669 f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
7670 WindowFromPoint (pt));
7671 }
7672
7673 /* If not, is it one of our scroll bars? */
7674 if (! f1)
7675 {
7676 struct scroll_bar *bar
7677 = x_window_to_scroll_bar (WindowFromPoint (pt));
7678
7679 if (bar)
7680 {
7681 f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7682 }
7683 }
7684
7685 if (f1 == 0 && insist > 0)
7686 f1 = SELECTED_FRAME ();
7687
7688 if (f1)
7689 {
7690 /* Ok, we found a frame. Store all the values.
7691 last_mouse_glyph is a rectangle used to reduce the
7692 generation of mouse events. To not miss any motion
7693 events, we must divide the frame into rectangles of the
7694 size of the smallest character that could be displayed
7695 on it, i.e. into the same rectangles that matrices on
7696 the frame are divided into. */
7697
7698 #if OLD_REDISPLAY_CODE
7699 int ignore1, ignore2;
7700
7701 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
7702
7703 pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
7704 &last_mouse_glyph,
7705 FRAME_W32_DISPLAY_INFO (f1)->grabbed
7706 || insist);
7707 #else
7708 ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
7709 remember_mouse_glyph (f1, pt.x, pt.y);
7710 #endif
7711
7712 *bar_window = Qnil;
7713 *part = 0;
7714 *fp = f1;
7715 XSETINT (*x, pt.x);
7716 XSETINT (*y, pt.y);
7717 *time = last_mouse_movement_time;
7718 }
7719 }
7720 }
7721
7722 UNBLOCK_INPUT;
7723 }
7724
7725 \f
7726 /* Scroll bar support. */
7727
7728 /* Given a window ID, find the struct scroll_bar which manages it.
7729 This can be called in GC, so we have to make sure to strip off mark
7730 bits. */
7731
7732 static struct scroll_bar *
7733 x_window_to_scroll_bar (window_id)
7734 Window window_id;
7735 {
7736 Lisp_Object tail;
7737
7738 for (tail = Vframe_list;
7739 XGCTYPE (tail) == Lisp_Cons;
7740 tail = XCDR (tail))
7741 {
7742 Lisp_Object frame, bar, condemned;
7743
7744 frame = XCAR (tail);
7745 /* All elements of Vframe_list should be frames. */
7746 if (! GC_FRAMEP (frame))
7747 abort ();
7748
7749 /* Scan this frame's scroll bar list for a scroll bar with the
7750 right window ID. */
7751 condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
7752 for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
7753 /* This trick allows us to search both the ordinary and
7754 condemned scroll bar lists with one loop. */
7755 ! GC_NILP (bar) || (bar = condemned,
7756 condemned = Qnil,
7757 ! GC_NILP (bar));
7758 bar = XSCROLL_BAR (bar)->next)
7759 if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
7760 return XSCROLL_BAR (bar);
7761 }
7762
7763 return 0;
7764 }
7765
7766
7767 \f
7768 /* Set the thumb size and position of scroll bar BAR. We are currently
7769 displaying PORTION out of a whole WHOLE, and our position POSITION. */
7770
7771 static void
7772 w32_set_scroll_bar_thumb (bar, portion, position, whole)
7773 struct scroll_bar *bar;
7774 int portion, position, whole;
7775 {
7776 Window w = SCROLL_BAR_W32_WINDOW (bar);
7777 double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
7778 int sb_page, sb_pos;
7779 BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
7780
7781 if (whole)
7782 {
7783 /* Position scroll bar at rock bottom if the bottom of the
7784 buffer is visible. This avoids shinking the thumb away
7785 to nothing if it is held at the bottom of the buffer. */
7786 if (position + portion >= whole)
7787 {
7788 sb_page = range * (whole - position) / whole
7789 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7790 sb_pos = range;
7791 }
7792
7793 sb_page = portion * range / whole + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7794 sb_pos = position * range / whole;
7795 }
7796 else
7797 {
7798 sb_page = range;
7799 sb_pos = 0;
7800 }
7801
7802 BLOCK_INPUT;
7803
7804 if (pfnSetScrollInfo)
7805 {
7806 SCROLLINFO si;
7807
7808 si.cbSize = sizeof (si);
7809 /* Only update page size if currently dragging, to reduce
7810 flicker effects. */
7811 if (draggingp)
7812 si.fMask = SIF_PAGE;
7813 else
7814 si.fMask = SIF_PAGE | SIF_POS;
7815 si.nPage = sb_page;
7816 si.nPos = sb_pos;
7817
7818 pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
7819 }
7820 else
7821 SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
7822
7823 UNBLOCK_INPUT;
7824 }
7825
7826 \f
7827 /************************************************************************
7828 Scroll bars, general
7829 ************************************************************************/
7830
7831 HWND
7832 my_create_scrollbar (f, bar)
7833 struct frame * f;
7834 struct scroll_bar * bar;
7835 {
7836 return (HWND) SendMessage (FRAME_W32_WINDOW (f),
7837 WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
7838 (LPARAM) bar);
7839 }
7840
7841 //#define ATTACH_THREADS
7842
7843 BOOL
7844 my_show_window (FRAME_PTR f, HWND hwnd, int how)
7845 {
7846 #ifndef ATTACH_THREADS
7847 return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
7848 (WPARAM) hwnd, (LPARAM) how);
7849 #else
7850 return ShowWindow (hwnd, how);
7851 #endif
7852 }
7853
7854 void
7855 my_set_window_pos (HWND hwnd, HWND hwndAfter,
7856 int x, int y, int cx, int cy, UINT flags)
7857 {
7858 #ifndef ATTACH_THREADS
7859 WINDOWPOS pos;
7860 pos.hwndInsertAfter = hwndAfter;
7861 pos.x = x;
7862 pos.y = y;
7863 pos.cx = cx;
7864 pos.cy = cy;
7865 pos.flags = flags;
7866 SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
7867 #else
7868 SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
7869 #endif
7870 }
7871
7872 void
7873 my_set_focus (f, hwnd)
7874 struct frame * f;
7875 HWND hwnd;
7876 {
7877 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
7878 (WPARAM) hwnd, 0);
7879 }
7880
7881 void
7882 my_set_foreground_window (hwnd)
7883 HWND hwnd;
7884 {
7885 SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
7886 }
7887
7888 void
7889 my_destroy_window (f, hwnd)
7890 struct frame * f;
7891 HWND hwnd;
7892 {
7893 SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
7894 (WPARAM) hwnd, 0);
7895 }
7896
7897 /* Create a scroll bar and return the scroll bar vector for it. W is
7898 the Emacs window on which to create the scroll bar. TOP, LEFT,
7899 WIDTH and HEIGHT are.the pixel coordinates and dimensions of the
7900 scroll bar. */
7901
7902 static struct scroll_bar *
7903 x_scroll_bar_create (w, top, left, width, height)
7904 struct window *w;
7905 int top, left, width, height;
7906 {
7907 struct frame *f = XFRAME (WINDOW_FRAME (w));
7908 HWND hwnd;
7909 struct scroll_bar *bar
7910 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
7911
7912 BLOCK_INPUT;
7913
7914 XSETWINDOW (bar->window, w);
7915 XSETINT (bar->top, top);
7916 XSETINT (bar->left, left);
7917 XSETINT (bar->width, width);
7918 XSETINT (bar->height, height);
7919 XSETINT (bar->start, 0);
7920 XSETINT (bar->end, 0);
7921 bar->dragging = Qnil;
7922
7923 /* Requires geometry to be set before call to create the real window */
7924
7925 hwnd = my_create_scrollbar (f, bar);
7926
7927 if (pfnSetScrollInfo)
7928 {
7929 SCROLLINFO si;
7930
7931 si.cbSize = sizeof (si);
7932 si.fMask = SIF_ALL;
7933 si.nMin = 0;
7934 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
7935 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7936 si.nPage = si.nMax;
7937 si.nPos = 0;
7938
7939 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
7940 }
7941 else
7942 {
7943 SetScrollRange (hwnd, SB_CTL, 0,
7944 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
7945 SetScrollPos (hwnd, SB_CTL, 0, FALSE);
7946 }
7947
7948 SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
7949
7950 /* Add bar to its frame's list of scroll bars. */
7951 bar->next = FRAME_SCROLL_BARS (f);
7952 bar->prev = Qnil;
7953 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
7954 if (! NILP (bar->next))
7955 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
7956
7957 UNBLOCK_INPUT;
7958
7959 return bar;
7960 }
7961
7962
7963 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
7964 nil. */
7965
7966 static void
7967 x_scroll_bar_remove (bar)
7968 struct scroll_bar *bar;
7969 {
7970 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
7971
7972 BLOCK_INPUT;
7973
7974 /* Destroy the window. */
7975 my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
7976
7977 /* Disassociate this scroll bar from its window. */
7978 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
7979
7980 UNBLOCK_INPUT;
7981 }
7982
7983 /* Set the handle of the vertical scroll bar for WINDOW to indicate
7984 that we are displaying PORTION characters out of a total of WHOLE
7985 characters, starting at POSITION. If WINDOW has no scroll bar,
7986 create one. */
7987 static void
7988 w32_set_vertical_scroll_bar (w, portion, whole, position)
7989 struct window *w;
7990 int portion, whole, position;
7991 {
7992 struct frame *f = XFRAME (w->frame);
7993 struct scroll_bar *bar;
7994 int top, height, left, sb_left, width, sb_width;
7995 int window_x, window_y, window_width, window_height;
7996
7997 /* Get window dimensions. */
7998 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
7999 top = window_y;
8000 width = FRAME_SCROLL_BAR_COLS (f) * CANON_X_UNIT (f);
8001 height = window_height;
8002
8003 /* Compute the left edge of the scroll bar area. */
8004 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8005 left = XINT (w->left) + XINT (w->width) - FRAME_SCROLL_BAR_COLS (f);
8006 else
8007 left = XFASTINT (w->left);
8008 left *= CANON_X_UNIT (f);
8009 left += FRAME_INTERNAL_BORDER_WIDTH (f);
8010
8011 /* Compute the width of the scroll bar which might be less than
8012 the width of the area reserved for the scroll bar. */
8013 if (FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0)
8014 sb_width = FRAME_SCROLL_BAR_PIXEL_WIDTH (f);
8015 else
8016 sb_width = width;
8017
8018 /* Compute the left edge of the scroll bar. */
8019 if (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_RIGHT (f))
8020 sb_left = left + width - sb_width - (width - sb_width) / 2;
8021 else
8022 sb_left = left + (width - sb_width) / 2;
8023
8024 /* Does the scroll bar exist yet? */
8025 if (NILP (w->vertical_scroll_bar))
8026 {
8027 HDC hdc;
8028 BLOCK_INPUT;
8029 if (width > 0 && height > 0)
8030 {
8031 hdc = get_frame_dc (f);
8032 w32_clear_area (f, hdc, left, top, width, height);
8033 release_frame_dc (f, hdc);
8034 }
8035 UNBLOCK_INPUT;
8036
8037 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
8038 }
8039 else
8040 {
8041 /* It may just need to be moved and resized. */
8042 HWND hwnd;
8043
8044 bar = XSCROLL_BAR (w->vertical_scroll_bar);
8045 hwnd = SCROLL_BAR_W32_WINDOW (bar);
8046
8047 /* If already correctly positioned, do nothing. */
8048 if ( XINT (bar->left) == sb_left
8049 && XINT (bar->top) == top
8050 && XINT (bar->width) == sb_width
8051 && XINT (bar->height) == height )
8052 {
8053 /* Redraw after clear_frame. */
8054 if (!my_show_window (f, hwnd, SW_NORMAL))
8055 InvalidateRect (hwnd, NULL, FALSE);
8056 }
8057 else
8058 {
8059 HDC hdc;
8060 BLOCK_INPUT;
8061 if (width && height)
8062 {
8063 hdc = get_frame_dc (f);
8064 /* Since Windows scroll bars are smaller than the space reserved
8065 for them on the frame, we have to clear "under" them. */
8066 w32_clear_area (f, hdc,
8067 left,
8068 top,
8069 width,
8070 height);
8071 release_frame_dc (f, hdc);
8072 }
8073 /* Make sure scroll bar is "visible" before moving, to ensure the
8074 area of the parent window now exposed will be refreshed. */
8075 my_show_window (f, hwnd, SW_HIDE);
8076 MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
8077 top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
8078 max (height, 1), TRUE);
8079 if (pfnSetScrollInfo)
8080 {
8081 SCROLLINFO si;
8082
8083 si.cbSize = sizeof (si);
8084 si.fMask = SIF_RANGE;
8085 si.nMin = 0;
8086 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
8087 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
8088
8089 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
8090 }
8091 else
8092 SetScrollRange (hwnd, SB_CTL, 0,
8093 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
8094 my_show_window (f, hwnd, SW_NORMAL);
8095 // InvalidateRect (w, NULL, FALSE);
8096
8097 /* Remember new settings. */
8098 XSETINT (bar->left, sb_left);
8099 XSETINT (bar->top, top);
8100 XSETINT (bar->width, sb_width);
8101 XSETINT (bar->height, height);
8102
8103 UNBLOCK_INPUT;
8104 }
8105 }
8106 w32_set_scroll_bar_thumb (bar, portion, position, whole);
8107
8108 XSETVECTOR (w->vertical_scroll_bar, bar);
8109 }
8110
8111
8112 /* The following three hooks are used when we're doing a thorough
8113 redisplay of the frame. We don't explicitly know which scroll bars
8114 are going to be deleted, because keeping track of when windows go
8115 away is a real pain - "Can you say set-window-configuration, boys
8116 and girls?" Instead, we just assert at the beginning of redisplay
8117 that *all* scroll bars are to be removed, and then save a scroll bar
8118 from the fiery pit when we actually redisplay its window. */
8119
8120 /* Arrange for all scroll bars on FRAME to be removed at the next call
8121 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
8122 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
8123
8124 static void
8125 w32_condemn_scroll_bars (frame)
8126 FRAME_PTR frame;
8127 {
8128 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
8129 while (! NILP (FRAME_SCROLL_BARS (frame)))
8130 {
8131 Lisp_Object bar;
8132 bar = FRAME_SCROLL_BARS (frame);
8133 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
8134 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
8135 XSCROLL_BAR (bar)->prev = Qnil;
8136 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
8137 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
8138 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
8139 }
8140 }
8141
8142
8143 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
8144 Note that WINDOW isn't necessarily condemned at all. */
8145
8146 static void
8147 w32_redeem_scroll_bar (window)
8148 struct window *window;
8149 {
8150 struct scroll_bar *bar;
8151 struct frame *f;
8152
8153 /* We can't redeem this window's scroll bar if it doesn't have one. */
8154 if (NILP (window->vertical_scroll_bar))
8155 abort ();
8156
8157 bar = XSCROLL_BAR (window->vertical_scroll_bar);
8158
8159 /* Unlink it from the condemned list. */
8160 f = XFRAME (WINDOW_FRAME (window));
8161 if (NILP (bar->prev))
8162 {
8163 /* If the prev pointer is nil, it must be the first in one of
8164 the lists. */
8165 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
8166 /* It's not condemned. Everything's fine. */
8167 return;
8168 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
8169 window->vertical_scroll_bar))
8170 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
8171 else
8172 /* If its prev pointer is nil, it must be at the front of
8173 one or the other! */
8174 abort ();
8175 }
8176 else
8177 XSCROLL_BAR (bar->prev)->next = bar->next;
8178
8179 if (! NILP (bar->next))
8180 XSCROLL_BAR (bar->next)->prev = bar->prev;
8181
8182 bar->next = FRAME_SCROLL_BARS (f);
8183 bar->prev = Qnil;
8184 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
8185 if (! NILP (bar->next))
8186 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
8187 }
8188
8189 /* Remove all scroll bars on FRAME that haven't been saved since the
8190 last call to `*condemn_scroll_bars_hook'. */
8191
8192 static void
8193 w32_judge_scroll_bars (f)
8194 FRAME_PTR f;
8195 {
8196 Lisp_Object bar, next;
8197
8198 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
8199
8200 /* Clear out the condemned list now so we won't try to process any
8201 more events on the hapless scroll bars. */
8202 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
8203
8204 for (; ! NILP (bar); bar = next)
8205 {
8206 struct scroll_bar *b = XSCROLL_BAR (bar);
8207
8208 x_scroll_bar_remove (b);
8209
8210 next = b->next;
8211 b->next = b->prev = Qnil;
8212 }
8213
8214 /* Now there should be no references to the condemned scroll bars,
8215 and they should get garbage-collected. */
8216 }
8217
8218 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
8219 is set to something other than no_event, it is enqueued.
8220
8221 This may be called from a signal handler, so we have to ignore GC
8222 mark bits. */
8223
8224 static int
8225 w32_scroll_bar_handle_click (bar, msg, emacs_event)
8226 struct scroll_bar *bar;
8227 W32Msg *msg;
8228 struct input_event *emacs_event;
8229 {
8230 if (! GC_WINDOWP (bar->window))
8231 abort ();
8232
8233 emacs_event->kind = w32_scroll_bar_click;
8234 emacs_event->code = 0;
8235 /* not really meaningful to distinguish up/down */
8236 emacs_event->modifiers = msg->dwModifiers;
8237 emacs_event->frame_or_window = bar->window;
8238 emacs_event->arg = Qnil;
8239 emacs_event->timestamp = msg->msg.time;
8240
8241 {
8242 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8243 int y;
8244 int dragging = !NILP (bar->dragging);
8245
8246 if (pfnGetScrollInfo)
8247 {
8248 SCROLLINFO si;
8249
8250 si.cbSize = sizeof (si);
8251 si.fMask = SIF_POS;
8252
8253 pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
8254 y = si.nPos;
8255 }
8256 else
8257 y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
8258
8259 bar->dragging = Qnil;
8260
8261
8262 last_mouse_scroll_bar_pos = msg->msg.wParam;
8263
8264 switch (LOWORD (msg->msg.wParam))
8265 {
8266 case SB_LINEDOWN:
8267 emacs_event->part = scroll_bar_down_arrow;
8268 break;
8269 case SB_LINEUP:
8270 emacs_event->part = scroll_bar_up_arrow;
8271 break;
8272 case SB_PAGEUP:
8273 emacs_event->part = scroll_bar_above_handle;
8274 break;
8275 case SB_PAGEDOWN:
8276 emacs_event->part = scroll_bar_below_handle;
8277 break;
8278 case SB_TOP:
8279 emacs_event->part = scroll_bar_handle;
8280 y = 0;
8281 break;
8282 case SB_BOTTOM:
8283 emacs_event->part = scroll_bar_handle;
8284 y = top_range;
8285 break;
8286 case SB_THUMBTRACK:
8287 case SB_THUMBPOSITION:
8288 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
8289 y = HIWORD (msg->msg.wParam);
8290 bar->dragging = Qt;
8291 emacs_event->part = scroll_bar_handle;
8292
8293 /* "Silently" update current position. */
8294 if (pfnSetScrollInfo)
8295 {
8296 SCROLLINFO si;
8297
8298 si.cbSize = sizeof (si);
8299 si.fMask = SIF_POS;
8300 si.nPos = y;
8301 /* Remember apparent position (we actually lag behind the real
8302 position, so don't set that directly. */
8303 last_scroll_bar_drag_pos = y;
8304
8305 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
8306 }
8307 else
8308 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
8309 break;
8310 case SB_ENDSCROLL:
8311 /* If this is the end of a drag sequence, then reset the scroll
8312 handle size to normal and do a final redraw. Otherwise do
8313 nothing. */
8314 if (dragging)
8315 {
8316 if (pfnSetScrollInfo)
8317 {
8318 SCROLLINFO si;
8319 int start = XINT (bar->start);
8320 int end = XINT (bar->end);
8321
8322 si.cbSize = sizeof (si);
8323 si.fMask = SIF_PAGE | SIF_POS;
8324 si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
8325 si.nPos = last_scroll_bar_drag_pos;
8326 pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
8327 }
8328 else
8329 SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
8330 }
8331 /* fall through */
8332 default:
8333 emacs_event->kind = no_event;
8334 return FALSE;
8335 }
8336
8337 XSETINT (emacs_event->x, y);
8338 XSETINT (emacs_event->y, top_range);
8339
8340 return TRUE;
8341 }
8342 }
8343
8344 /* Return information to the user about the current position of the mouse
8345 on the scroll bar. */
8346
8347 static void
8348 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
8349 FRAME_PTR *fp;
8350 Lisp_Object *bar_window;
8351 enum scroll_bar_part *part;
8352 Lisp_Object *x, *y;
8353 unsigned long *time;
8354 {
8355 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
8356 Window w = SCROLL_BAR_W32_WINDOW (bar);
8357 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
8358 int pos;
8359 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
8360
8361 BLOCK_INPUT;
8362
8363 *fp = f;
8364 *bar_window = bar->window;
8365
8366 if (pfnGetScrollInfo)
8367 {
8368 SCROLLINFO si;
8369
8370 si.cbSize = sizeof (si);
8371 si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
8372
8373 pfnGetScrollInfo (w, SB_CTL, &si);
8374 pos = si.nPos;
8375 top_range = si.nMax - si.nPage + 1;
8376 }
8377 else
8378 pos = GetScrollPos (w, SB_CTL);
8379
8380 switch (LOWORD (last_mouse_scroll_bar_pos))
8381 {
8382 case SB_THUMBPOSITION:
8383 case SB_THUMBTRACK:
8384 *part = scroll_bar_handle;
8385 if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
8386 pos = HIWORD (last_mouse_scroll_bar_pos);
8387 break;
8388 case SB_LINEDOWN:
8389 *part = scroll_bar_handle;
8390 pos++;
8391 break;
8392 default:
8393 *part = scroll_bar_handle;
8394 break;
8395 }
8396
8397 XSETINT (*x, pos);
8398 XSETINT (*y, top_range);
8399
8400 f->mouse_moved = 0;
8401 last_mouse_scroll_bar = Qnil;
8402
8403 *time = last_mouse_movement_time;
8404
8405 UNBLOCK_INPUT;
8406 }
8407
8408
8409 /* The screen has been cleared so we may have changed foreground or
8410 background colors, and the scroll bars may need to be redrawn.
8411 Clear out the scroll bars, and ask for expose events, so we can
8412 redraw them. */
8413
8414 void
8415 x_scroll_bar_clear (f)
8416 FRAME_PTR f;
8417 {
8418 Lisp_Object bar;
8419
8420 /* We can have scroll bars even if this is 0,
8421 if we just turned off scroll bar mode.
8422 But in that case we should not clear them. */
8423 if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
8424 for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
8425 bar = XSCROLL_BAR (bar)->next)
8426 {
8427 HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
8428 HDC hdc = GetDC (window);
8429 RECT rect;
8430
8431 /* Hide scroll bar until ready to repaint. x_scroll_bar_move
8432 arranges to refresh the scroll bar if hidden. */
8433 my_show_window (f, window, SW_HIDE);
8434
8435 GetClientRect (window, &rect);
8436 select_palette (f, hdc);
8437 w32_clear_rect (f, hdc, &rect);
8438 deselect_palette (f, hdc);
8439
8440 ReleaseDC (window, hdc);
8441 }
8442 }
8443
8444 \f
8445 /* The main W32 event-reading loop - w32_read_socket. */
8446
8447 /* Time stamp of enter window event. This is only used by w32_read_socket,
8448 but we have to put it out here, since static variables within functions
8449 sometimes don't work. */
8450
8451 static Time enter_timestamp;
8452
8453 /* Record the last 100 characters stored
8454 to help debug the loss-of-chars-during-GC problem. */
8455
8456 static int temp_index;
8457 static short temp_buffer[100];
8458
8459
8460 /* Read events coming from the W32 shell.
8461 This routine is called by the SIGIO handler.
8462 We return as soon as there are no more events to be read.
8463
8464 Events representing keys are stored in buffer BUFP,
8465 which can hold up to NUMCHARS characters.
8466 We return the number of characters stored into the buffer,
8467 thus pretending to be `read'.
8468
8469 EXPECTED is nonzero if the caller knows input is available.
8470
8471 Some of these messages are reposted back to the message queue since the
8472 system calls the windows proc directly in a context where we cannot return
8473 the data nor can we guarantee the state we are in. So if we dispatch them
8474 we will get into an infinite loop. To prevent this from ever happening we
8475 will set a variable to indicate we are in the read_socket call and indicate
8476 which message we are processing since the windows proc gets called
8477 recursively with different messages by the system.
8478 */
8479
8480 int
8481 w32_read_socket (sd, bufp, numchars, expected)
8482 register int sd;
8483 /* register */ struct input_event *bufp;
8484 /* register */ int numchars;
8485 int expected;
8486 {
8487 int count = 0;
8488 int check_visibility = 0;
8489 W32Msg msg;
8490 struct frame *f;
8491 struct w32_display_info *dpyinfo = &one_w32_display_info;
8492
8493 if (interrupt_input_blocked)
8494 {
8495 interrupt_input_pending = 1;
8496 return -1;
8497 }
8498
8499 interrupt_input_pending = 0;
8500 BLOCK_INPUT;
8501
8502 /* So people can tell when we have read the available input. */
8503 input_signal_count++;
8504
8505 if (numchars <= 0)
8506 abort (); /* Don't think this happens. */
8507
8508 /* TODO: tool-bars, ghostscript integration, mouse
8509 cursors. */
8510 while (get_next_msg (&msg, FALSE))
8511 {
8512 switch (msg.msg.message)
8513 {
8514 case WM_PAINT:
8515 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8516
8517 if (f)
8518 {
8519 if (msg.rect.right == msg.rect.left ||
8520 msg.rect.bottom == msg.rect.top)
8521 {
8522 /* We may get paint messages even though the client
8523 area is clipped - these are not expose events. */
8524 DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
8525 XSTRING (f->name)->data));
8526 }
8527 else if (f->async_visible != 1)
8528 {
8529 /* Definitely not obscured, so mark as visible. */
8530 f->async_visible = 1;
8531 f->async_iconified = 0;
8532 SET_FRAME_GARBAGED (f);
8533 DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
8534 XSTRING (f->name)->data));
8535
8536 /* WM_PAINT serves as MapNotify as well, so report
8537 visibility changes properly. */
8538 if (f->iconified)
8539 {
8540 bufp->kind = deiconify_event;
8541 XSETFRAME (bufp->frame_or_window, f);
8542 bufp->arg = Qnil;
8543 bufp++;
8544 count++;
8545 numchars--;
8546 }
8547 else if (! NILP (Vframe_list)
8548 && ! NILP (XCDR (Vframe_list)))
8549 /* Force a redisplay sooner or later to update the
8550 frame titles in case this is the second frame. */
8551 record_asynch_buffer_change ();
8552 }
8553 else
8554 {
8555 HDC hdc = get_frame_dc (f);
8556
8557 /* Erase background again for safety. */
8558 w32_clear_rect (f, hdc, &msg.rect);
8559 release_frame_dc (f, hdc);
8560 expose_frame (f,
8561 msg.rect.left,
8562 msg.rect.top,
8563 msg.rect.right - msg.rect.left,
8564 msg.rect.bottom - msg.rect.top);
8565 }
8566 }
8567 break;
8568
8569 case WM_INPUTLANGCHANGE:
8570 /* Generate a language change event. */
8571 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8572
8573 if (f)
8574 {
8575 if (numchars == 0)
8576 abort ();
8577
8578 bufp->kind = language_change_event;
8579 XSETFRAME (bufp->frame_or_window, f);
8580 bufp->arg = Qnil;
8581 bufp->code = msg.msg.wParam;
8582 bufp->modifiers = msg.msg.lParam & 0xffff;
8583 bufp++;
8584 count++;
8585 numchars--;
8586 }
8587 break;
8588
8589 case WM_KEYDOWN:
8590 case WM_SYSKEYDOWN:
8591 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8592
8593 if (f && !f->iconified)
8594 {
8595 if (temp_index == sizeof temp_buffer / sizeof (short))
8596 temp_index = 0;
8597 temp_buffer[temp_index++] = msg.msg.wParam;
8598 bufp->kind = non_ascii_keystroke;
8599 bufp->code = msg.msg.wParam;
8600 bufp->modifiers = msg.dwModifiers;
8601 XSETFRAME (bufp->frame_or_window, f);
8602 bufp->arg = Qnil;
8603 bufp->timestamp = msg.msg.time;
8604 bufp++;
8605 numchars--;
8606 count++;
8607 }
8608 break;
8609
8610 case WM_SYSCHAR:
8611 case WM_CHAR:
8612 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8613
8614 if (f && !f->iconified)
8615 {
8616 if (temp_index == sizeof temp_buffer / sizeof (short))
8617 temp_index = 0;
8618 temp_buffer[temp_index++] = msg.msg.wParam;
8619 bufp->kind = ascii_keystroke;
8620 bufp->code = msg.msg.wParam;
8621 bufp->modifiers = msg.dwModifiers;
8622 XSETFRAME (bufp->frame_or_window, f);
8623 bufp->arg = Qnil;
8624 bufp->timestamp = msg.msg.time;
8625 bufp++;
8626 numchars--;
8627 count++;
8628 }
8629 break;
8630
8631 case WM_MOUSEMOVE:
8632 previous_help_echo = help_echo;
8633 help_echo_object = help_echo_window = Qnil;
8634 help_echo_pos = -1;
8635
8636 if (dpyinfo->grabbed && last_mouse_frame
8637 && FRAME_LIVE_P (last_mouse_frame))
8638 f = last_mouse_frame;
8639 else
8640 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8641
8642 if (f)
8643 note_mouse_movement (f, &msg.msg);
8644 else
8645 {
8646 /* If we move outside the frame, then we're
8647 certainly no longer on any text in the frame. */
8648 clear_mouse_face (dpyinfo);
8649 }
8650
8651 /* If the contents of the global variable help_echo
8652 has changed, generate a HELP_EVENT. */
8653 if (help_echo != previous_help_echo)
8654 {
8655 Lisp_Object frame;
8656 int n;
8657
8658 if (f)
8659 XSETFRAME (frame, f);
8660 else
8661 frame = Qnil;
8662
8663 any_help_event_p = 1;
8664 n = gen_help_event (bufp, numchars, help_echo, frame,
8665 help_echo_window, help_echo_object,
8666 help_echo_pos);
8667 bufp += n, count += n, numchars -= n;
8668 }
8669 break;
8670
8671 case WM_LBUTTONDOWN:
8672 case WM_LBUTTONUP:
8673 case WM_MBUTTONDOWN:
8674 case WM_MBUTTONUP:
8675 case WM_RBUTTONDOWN:
8676 case WM_RBUTTONUP:
8677 case WM_XBUTTONDOWN:
8678 case WM_XBUTTONUP:
8679 {
8680 /* If we decide we want to generate an event to be seen
8681 by the rest of Emacs, we put it here. */
8682 struct input_event emacs_event;
8683 int tool_bar_p = 0;
8684 int button;
8685 int up;
8686
8687 emacs_event.kind = no_event;
8688
8689 if (dpyinfo->grabbed && last_mouse_frame
8690 && FRAME_LIVE_P (last_mouse_frame))
8691 f = last_mouse_frame;
8692 else
8693 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8694
8695 if (f)
8696 {
8697 construct_mouse_click (&emacs_event, &msg, f);
8698
8699 /* Is this in the tool-bar? */
8700 if (WINDOWP (f->tool_bar_window)
8701 && XFASTINT (XWINDOW (f->tool_bar_window)->height))
8702 {
8703 Lisp_Object window;
8704 int p;
8705
8706 /* Set x and y. */
8707 window = window_from_coordinates (f,
8708 emacs_event.x,
8709 emacs_event.y,
8710 &p, 1);
8711 if (EQ (window, f->tool_bar_window))
8712 {
8713 w32_handle_tool_bar_click (f, &emacs_event);
8714 tool_bar_p = 1;
8715 }
8716 }
8717
8718 if (!tool_bar_p)
8719 if (!dpyinfo->w32_focus_frame
8720 || f == dpyinfo->w32_focus_frame
8721 && (numchars >= 1))
8722 {
8723 construct_mouse_click (bufp, &msg, f);
8724 bufp++;
8725 count++;
8726 numchars--;
8727 }
8728 }
8729
8730 parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
8731 &button, &up);
8732
8733 if (up)
8734 {
8735 dpyinfo->grabbed &= ~ (1 << button);
8736 }
8737 else
8738 {
8739 dpyinfo->grabbed |= (1 << button);
8740 last_mouse_frame = f;
8741 /* Ignore any mouse motion that happened
8742 before this event; any subsequent mouse-movement
8743 Emacs events should reflect only motion after
8744 the ButtonPress. */
8745 if (f != 0)
8746 f->mouse_moved = 0;
8747
8748 if (!tool_bar_p)
8749 last_tool_bar_item = -1;
8750 }
8751 break;
8752 }
8753
8754 case WM_MOUSEWHEEL:
8755 if (dpyinfo->grabbed && last_mouse_frame
8756 && FRAME_LIVE_P (last_mouse_frame))
8757 f = last_mouse_frame;
8758 else
8759 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8760
8761 if (f)
8762 {
8763 if ((!dpyinfo->w32_focus_frame
8764 || f == dpyinfo->w32_focus_frame)
8765 && (numchars >= 1))
8766 {
8767 construct_mouse_wheel (bufp, &msg, f);
8768 bufp++;
8769 count++;
8770 numchars--;
8771 }
8772 }
8773 break;
8774
8775 case WM_DROPFILES:
8776 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8777
8778 if (f)
8779 {
8780 construct_drag_n_drop (bufp, &msg, f);
8781 bufp++;
8782 count++;
8783 numchars--;
8784 }
8785 break;
8786
8787 case WM_VSCROLL:
8788 {
8789 struct scroll_bar *bar =
8790 x_window_to_scroll_bar ((HWND)msg.msg.lParam);
8791
8792 if (bar && numchars >= 1)
8793 {
8794 if (w32_scroll_bar_handle_click (bar, &msg, bufp))
8795 {
8796 bufp++;
8797 count++;
8798 numchars--;
8799 }
8800 }
8801 break;
8802 }
8803
8804 case WM_WINDOWPOSCHANGED:
8805 case WM_ACTIVATE:
8806 case WM_ACTIVATEAPP:
8807 check_visibility = 1;
8808 break;
8809
8810 case WM_MOVE:
8811 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8812
8813 if (f && !f->async_iconified)
8814 {
8815 int x, y;
8816
8817 x_real_positions (f, &x, &y);
8818 f->output_data.w32->left_pos = x;
8819 f->output_data.w32->top_pos = y;
8820 }
8821
8822 check_visibility = 1;
8823 break;
8824
8825 case WM_SHOWWINDOW:
8826 /* wParam non-zero means Window is about to be shown, 0 means
8827 about to be hidden. */
8828 /* Redo the mouse-highlight after the tooltip has gone. */
8829 if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
8830 {
8831 tip_window = NULL;
8832 redo_mouse_highlight ();
8833 }
8834
8835 /* If window has been obscured or exposed by another window
8836 being maximised or minimised/restored, then recheck
8837 visibility of all frames. Direct changes to our own
8838 windows get handled by WM_SIZE. */
8839 #if 0
8840 if (msg.msg.lParam != 0)
8841 check_visibility = 1;
8842 else
8843 {
8844 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8845 f->async_visible = msg.msg.wParam;
8846 }
8847 #endif
8848
8849 check_visibility = 1;
8850 break;
8851
8852 case WM_SIZE:
8853 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
8854
8855 /* Inform lisp of whether frame has been iconified etc. */
8856 if (f)
8857 {
8858 switch (msg.msg.wParam)
8859 {
8860 case SIZE_MINIMIZED:
8861 f->async_visible = 0;
8862 f->async_iconified = 1;
8863
8864 bufp->kind = iconify_event;
8865 XSETFRAME (bufp->frame_or_window, f);
8866 bufp->arg = Qnil;
8867 bufp++;
8868 count++;
8869 numchars--;
8870 break;
8871
8872 case SIZE_MAXIMIZED:
8873 case SIZE_RESTORED:
8874 f->async_visible = 1;
8875 f->async_iconified = 0;
8876
8877 /* wait_reading_process_input will notice this and update
8878 the frame's display structures. */
8879 SET_FRAME_GARBAGED (f);
8880
8881 if (f->iconified)
8882 {
8883 int x, y;
8884
8885 /* Reset top and left positions of the Window
8886 here since Windows sends a WM_MOVE message
8887 BEFORE telling us the Window is minimized
8888 when the Window is iconified, with 3000,3000
8889 as the co-ords. */
8890 x_real_positions (f, &x, &y);
8891 f->output_data.w32->left_pos = x;
8892 f->output_data.w32->top_pos = y;
8893
8894 bufp->kind = deiconify_event;
8895 XSETFRAME (bufp->frame_or_window, f);
8896 bufp->arg = Qnil;
8897 bufp++;
8898 count++;
8899 numchars--;
8900 }
8901 else if (! NILP (Vframe_list)
8902 && ! NILP (XCDR (Vframe_list)))
8903 /* Force a redisplay sooner or later
8904 to update the frame titles
8905 in case this is the second frame. */
8906 record_asynch_buffer_change ();
8907 break;
8908 }
8909 }
8910
8911 if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
8912 {
8913 RECT rect;
8914 int rows;
8915 int columns;
8916 int width;
8917 int height;
8918
8919 GetClientRect (msg.msg.hwnd, &rect);
8920
8921 height = rect.bottom - rect.top;
8922 width = rect.right - rect.left;
8923
8924 rows = PIXEL_TO_CHAR_HEIGHT (f, height);
8925 columns = PIXEL_TO_CHAR_WIDTH (f, width);
8926
8927 /* TODO: Clip size to the screen dimensions. */
8928
8929 /* Even if the number of character rows and columns has
8930 not changed, the font size may have changed, so we need
8931 to check the pixel dimensions as well. */
8932
8933 if (columns != f->width
8934 || rows != f->height
8935 || width != f->output_data.w32->pixel_width
8936 || height != f->output_data.w32->pixel_height)
8937 {
8938 change_frame_size (f, rows, columns, 0, 1, 0);
8939 SET_FRAME_GARBAGED (f);
8940 cancel_mouse_face (f);
8941 f->output_data.w32->pixel_width = width;
8942 f->output_data.w32->pixel_height = height;
8943 f->output_data.w32->win_gravity = NorthWestGravity;
8944 }
8945 }
8946
8947 check_visibility = 1;
8948 break;
8949
8950 case WM_MOUSELEAVE:
8951 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
8952 if (f)
8953 {
8954 if (f == dpyinfo->mouse_face_mouse_frame)
8955 {
8956 /* If we move outside the frame, then we're
8957 certainly no longer on any text in the frame. */
8958 clear_mouse_face (dpyinfo);
8959 dpyinfo->mouse_face_mouse_frame = 0;
8960 }
8961
8962 /* Generate a nil HELP_EVENT to cancel a help-echo.
8963 Do it only if there's something to cancel.
8964 Otherwise, the startup message is cleared when
8965 the mouse leaves the frame. */
8966 if (any_help_event_p)
8967 {
8968 Lisp_Object frame;
8969 int n;
8970
8971 XSETFRAME (frame, f);
8972 help_echo = Qnil;
8973 n = gen_help_event (bufp, numchars,
8974 Qnil, frame, Qnil, Qnil, 0);
8975 bufp += n, count += n, numchars -= n;
8976 }
8977 }
8978 break;
8979
8980 case WM_SETFOCUS:
8981 f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
8982
8983 dpyinfo->w32_focus_event_frame = f;
8984
8985 if (f)
8986 x_new_focus_frame (dpyinfo, f);
8987
8988
8989 dpyinfo->grabbed = 0;
8990 check_visibility = 1;
8991 break;
8992
8993 case WM_KILLFOCUS:
8994 /* TODO: some of this belongs in MOUSE_LEAVE */
8995 f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
8996
8997 if (f)
8998 {
8999 if (f == dpyinfo->w32_focus_event_frame)
9000 dpyinfo->w32_focus_event_frame = 0;
9001
9002 if (f == dpyinfo->w32_focus_frame)
9003 x_new_focus_frame (dpyinfo, 0);
9004
9005 if (f == dpyinfo->mouse_face_mouse_frame)
9006 {
9007 /* If we move outside the frame, then we're
9008 certainly no longer on any text in the frame. */
9009 clear_mouse_face (dpyinfo);
9010 dpyinfo->mouse_face_mouse_frame = 0;
9011 }
9012
9013 /* Generate a nil HELP_EVENT to cancel a help-echo.
9014 Do it only if there's something to cancel.
9015 Otherwise, the startup message is cleared when
9016 the mouse leaves the frame. */
9017 if (any_help_event_p)
9018 {
9019 Lisp_Object frame;
9020 int n;
9021
9022 XSETFRAME (frame, f);
9023 help_echo = Qnil;
9024 n = gen_help_event (bufp, numchars,
9025 Qnil, frame, Qnil, Qnil, 0);
9026 bufp += n, count += n, numchars -=n;
9027 }
9028 }
9029
9030 dpyinfo->grabbed = 0;
9031 check_visibility = 1;
9032 break;
9033
9034 case WM_CLOSE:
9035 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9036
9037 if (f)
9038 {
9039 if (numchars == 0)
9040 abort ();
9041
9042 bufp->kind = delete_window_event;
9043 XSETFRAME (bufp->frame_or_window, f);
9044 bufp->arg = Qnil;
9045 bufp++;
9046 count++;
9047 numchars--;
9048 }
9049 break;
9050
9051 case WM_INITMENU:
9052 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9053
9054 if (f)
9055 {
9056 if (numchars == 0)
9057 abort ();
9058
9059 bufp->kind = menu_bar_activate_event;
9060 XSETFRAME (bufp->frame_or_window, f);
9061 bufp->arg = Qnil;
9062 bufp++;
9063 count++;
9064 numchars--;
9065 }
9066 break;
9067
9068 case WM_COMMAND:
9069 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9070
9071 if (f)
9072 {
9073 extern void menubar_selection_callback
9074 (FRAME_PTR f, void * client_data);
9075 menubar_selection_callback (f, (void *)msg.msg.wParam);
9076 }
9077
9078 check_visibility = 1;
9079 break;
9080
9081 case WM_DISPLAYCHANGE:
9082 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9083
9084 if (f)
9085 {
9086 dpyinfo->width = (short) LOWORD (msg.msg.lParam);
9087 dpyinfo->height = (short) HIWORD (msg.msg.lParam);
9088 dpyinfo->n_cbits = msg.msg.wParam;
9089 DebPrint (("display change: %d %d\n", dpyinfo->width,
9090 dpyinfo->height));
9091 }
9092
9093 check_visibility = 1;
9094 break;
9095
9096 default:
9097 /* Check for messages registered at runtime. */
9098 if (msg.msg.message == msh_mousewheel)
9099 {
9100 if (dpyinfo->grabbed && last_mouse_frame
9101 && FRAME_LIVE_P (last_mouse_frame))
9102 f = last_mouse_frame;
9103 else
9104 f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
9105
9106 if (f)
9107 {
9108 if ((!dpyinfo->w32_focus_frame
9109 || f == dpyinfo->w32_focus_frame)
9110 && (numchars >= 1))
9111 {
9112 construct_mouse_wheel (bufp, &msg, f);
9113 bufp++;
9114 count++;
9115 numchars--;
9116 }
9117 }
9118 }
9119 break;
9120 }
9121 }
9122
9123 /* If the focus was just given to an autoraising frame,
9124 raise it now. */
9125 /* ??? This ought to be able to handle more than one such frame. */
9126 if (pending_autoraise_frame)
9127 {
9128 x_raise_frame (pending_autoraise_frame);
9129 pending_autoraise_frame = 0;
9130 }
9131
9132 /* Check which frames are still visisble, if we have enqueued any user
9133 events or been notified of events that may affect visibility. We
9134 do this here because there doesn't seem to be any direct
9135 notification from Windows that the visibility of a window has
9136 changed (at least, not in all cases). */
9137 if (count > 0 || check_visibility)
9138 {
9139 Lisp_Object tail, frame;
9140
9141 FOR_EACH_FRAME (tail, frame)
9142 {
9143 FRAME_PTR f = XFRAME (frame);
9144 /* The tooltip has been drawn already. Avoid the
9145 SET_FRAME_GARBAGED below. */
9146 if (EQ (frame, tip_frame))
9147 continue;
9148
9149 /* Check "visible" frames and mark each as obscured or not.
9150 Note that async_visible is nonzero for unobscured and
9151 obscured frames, but zero for hidden and iconified frames. */
9152 if (FRAME_W32_P (f) && f->async_visible)
9153 {
9154 RECT clipbox;
9155 HDC hdc;
9156
9157 enter_crit ();
9158 /* Query clipping rectangle for the entire window area
9159 (GetWindowDC), not just the client portion (GetDC).
9160 Otherwise, the scrollbars and menubar aren't counted as
9161 part of the visible area of the frame, and we may think
9162 the frame is obscured when really a scrollbar is still
9163 visible and gets WM_PAINT messages above. */
9164 hdc = GetWindowDC (FRAME_W32_WINDOW (f));
9165 GetClipBox (hdc, &clipbox);
9166 ReleaseDC (FRAME_W32_WINDOW (f), hdc);
9167 leave_crit ();
9168
9169 if (clipbox.right == clipbox.left
9170 || clipbox.bottom == clipbox.top)
9171 {
9172 /* Frame has become completely obscured so mark as
9173 such (we do this by setting async_visible to 2 so
9174 that FRAME_VISIBLE_P is still true, but redisplay
9175 will skip it). */
9176 f->async_visible = 2;
9177
9178 if (!FRAME_OBSCURED_P (f))
9179 {
9180 DebPrint (("frame %p (%s) obscured\n", f,
9181 XSTRING (f->name)->data));
9182 }
9183 }
9184 else
9185 {
9186 /* Frame is not obscured, so mark it as such. */
9187 f->async_visible = 1;
9188
9189 if (FRAME_OBSCURED_P (f))
9190 {
9191 SET_FRAME_GARBAGED (f);
9192 DebPrint (("obscured frame %p (%s) found to be visible\n", f,
9193 XSTRING (f->name)->data));
9194
9195 /* Force a redisplay sooner or later. */
9196 record_asynch_buffer_change ();
9197 }
9198 }
9199 }
9200 }
9201 }
9202
9203 UNBLOCK_INPUT;
9204 return count;
9205 }
9206
9207
9208
9209 \f
9210 /***********************************************************************
9211 Text Cursor
9212 ***********************************************************************/
9213
9214 /* Notice if the text cursor of window W has been overwritten by a
9215 drawing operation that outputs glyphs starting at START_X and
9216 ending at END_X in the line given by output_cursor.vpos.
9217 Coordinates are area-relative. END_X < 0 means all the rest
9218 of the line after START_X has been written. */
9219
9220 static void
9221 notice_overwritten_cursor (w, area, x0, x1, y0, y1)
9222 struct window *w;
9223 enum glyph_row_area area;
9224 int x0, x1, y0, y1;
9225 {
9226 if (area == TEXT_AREA
9227 && w->phys_cursor_on_p
9228 && y0 <= w->phys_cursor.y
9229 && y1 >= w->phys_cursor.y + w->phys_cursor_height
9230 && x0 <= w->phys_cursor.x
9231 && (x1 < 0 || x1 > w->phys_cursor.x))
9232 w->phys_cursor_on_p = 0;
9233 }
9234
9235
9236 /* Set clipping for output in glyph row ROW. W is the window in which
9237 we operate. GC is the graphics context to set clipping in.
9238 WHOLE_LINE_P non-zero means include the areas used for truncation
9239 mark display and alike in the clipping rectangle.
9240
9241 ROW may be a text row or, e.g., a mode line. Text rows must be
9242 clipped to the interior of the window dedicated to text display,
9243 mode lines must be clipped to the whole window. */
9244
9245 static void
9246 w32_clip_to_row (w, row, hdc, whole_line_p)
9247 struct window *w;
9248 struct glyph_row *row;
9249 HDC hdc;
9250 int whole_line_p;
9251 {
9252 struct frame *f = XFRAME (WINDOW_FRAME (w));
9253 RECT clip_rect;
9254 int window_x, window_y, window_width, window_height;
9255
9256 window_box (w, -1, &window_x, &window_y, &window_width, &window_height);
9257
9258 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
9259 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
9260 clip_rect.top = max (clip_rect.top, window_y);
9261 clip_rect.right = clip_rect.left + window_width;
9262 clip_rect.bottom = clip_rect.top + row->visible_height;
9263
9264 /* If clipping to the whole line, including trunc marks, extend
9265 the rectangle to the left and increase its width. */
9266 if (whole_line_p)
9267 {
9268 clip_rect.left -= FRAME_X_LEFT_FRINGE_WIDTH (f);
9269 clip_rect.right += FRAME_X_FRINGE_WIDTH (f);
9270 }
9271
9272 w32_set_clip_rectangle (hdc, &clip_rect);
9273 }
9274
9275
9276 /* Draw a hollow box cursor on window W in glyph row ROW. */
9277
9278 static void
9279 x_draw_hollow_cursor (w, row)
9280 struct window *w;
9281 struct glyph_row *row;
9282 {
9283 struct frame *f = XFRAME (WINDOW_FRAME (w));
9284 HDC hdc;
9285 RECT rect;
9286 int wd;
9287 struct glyph *cursor_glyph;
9288 HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
9289
9290 /* Compute frame-relative coordinates from window-relative
9291 coordinates. */
9292 rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9293 rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9294 + row->ascent - w->phys_cursor_ascent);
9295 rect.bottom = rect.top + row->height - 1;
9296
9297 /* Get the glyph the cursor is on. If we can't tell because
9298 the current matrix is invalid or such, give up. */
9299 cursor_glyph = get_phys_cursor_glyph (w);
9300 if (cursor_glyph == NULL)
9301 return;
9302
9303 /* Compute the width of the rectangle to draw. If on a stretch
9304 glyph, and `x-stretch-block-cursor' is nil, don't draw a
9305 rectangle as wide as the glyph, but use a canonical character
9306 width instead. */
9307 wd = cursor_glyph->pixel_width - 1;
9308 if (cursor_glyph->type == STRETCH_GLYPH
9309 && !x_stretch_cursor_p)
9310 wd = min (CANON_X_UNIT (f), wd);
9311
9312 rect.right = rect.left + wd;
9313 hdc = get_frame_dc (f);
9314 FrameRect (hdc, &rect, hb);
9315 DeleteObject (hb);
9316
9317 release_frame_dc (f, hdc);
9318 }
9319
9320
9321 /* Draw a bar cursor on window W in glyph row ROW.
9322
9323 Implementation note: One would like to draw a bar cursor with an
9324 angle equal to the one given by the font property XA_ITALIC_ANGLE.
9325 Unfortunately, I didn't find a font yet that has this property set.
9326 --gerd. */
9327
9328 static void
9329 x_draw_bar_cursor (w, row, width)
9330 struct window *w;
9331 struct glyph_row *row;
9332 int width;
9333 {
9334 struct frame *f = XFRAME (w->frame);
9335 struct glyph *cursor_glyph;
9336 int x;
9337 HDC hdc;
9338
9339 /* If cursor is out of bounds, don't draw garbage. This can happen
9340 in mini-buffer windows when switching between echo area glyphs
9341 and mini-buffer. */
9342 cursor_glyph = get_phys_cursor_glyph (w);
9343 if (cursor_glyph == NULL)
9344 return;
9345
9346 /* If on an image, draw like a normal cursor. That's usually better
9347 visible than drawing a bar, esp. if the image is large so that
9348 the bar might not be in the window. */
9349 if (cursor_glyph->type == IMAGE_GLYPH)
9350 {
9351 struct glyph_row *row;
9352 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
9353 x_draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
9354 }
9355 else
9356 {
9357 COLORREF cursor_color = f->output_data.w32->cursor_pixel;
9358 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
9359
9360 if (width < 0)
9361 width = f->output_data.w32->cursor_width;
9362
9363 /* If the glyph's background equals the color we normally draw
9364 the bar cursor in, the bar cursor in its normal color is
9365 invisible. Use the glyph's foreground color instead in this
9366 case, on the assumption that the glyph's colors are chosen so
9367 that the glyph is legible. */
9368 if (face->background == cursor_color)
9369 cursor_color = face->foreground;
9370
9371 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9372 hdc = get_frame_dc (f);
9373 w32_clip_to_row (w, row, hdc, 0);
9374 w32_fill_area (f, hdc, cursor_color, x,
9375 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
9376 min (cursor_glyph->pixel_width, width),
9377 row->height);
9378 release_frame_dc (f, hdc);
9379 }
9380 }
9381
9382
9383 /* Clear the cursor of window W to background color, and mark the
9384 cursor as not shown. This is used when the text where the cursor
9385 is is about to be rewritten. */
9386
9387 static void
9388 x_clear_cursor (w)
9389 struct window *w;
9390 {
9391 if (FRAME_VISIBLE_P (XFRAME (w->frame)) && w->phys_cursor_on_p)
9392 x_update_window_cursor (w, 0);
9393 }
9394
9395
9396 /* Draw the cursor glyph of window W in glyph row ROW. See the
9397 comment of x_draw_glyphs for the meaning of HL. */
9398
9399 static void
9400 x_draw_phys_cursor_glyph (w, row, hl)
9401 struct window *w;
9402 struct glyph_row *row;
9403 enum draw_glyphs_face hl;
9404 {
9405 /* If cursor hpos is out of bounds, don't draw garbage. This can
9406 happen in mini-buffer windows when switching between echo area
9407 glyphs and mini-buffer. */
9408 if (w->phys_cursor.hpos < row->used[TEXT_AREA])
9409 {
9410 int on_p = w->phys_cursor_on_p;
9411 x_draw_glyphs (w, w->phys_cursor.x, row, TEXT_AREA,
9412 w->phys_cursor.hpos, w->phys_cursor.hpos + 1,
9413 hl, 0);
9414 w->phys_cursor_on_p = on_p;
9415
9416 /* When we erase the cursor, and ROW is overlapped by other
9417 rows, make sure that these overlapping parts of other rows
9418 are redrawn. */
9419 if (hl == DRAW_NORMAL_TEXT && row->overlapped_p)
9420 {
9421 if (row > w->current_matrix->rows
9422 && MATRIX_ROW_OVERLAPS_SUCC_P (row - 1))
9423 x_fix_overlapping_area (w, row - 1, TEXT_AREA);
9424
9425 if (MATRIX_ROW_BOTTOM_Y (row) < window_text_bottom_y (w)
9426 && MATRIX_ROW_OVERLAPS_PRED_P (row + 1))
9427 x_fix_overlapping_area (w, row + 1, TEXT_AREA);
9428 }
9429 }
9430 }
9431
9432
9433 /* Erase the image of a cursor of window W from the screen. */
9434
9435 static void
9436 x_erase_phys_cursor (w)
9437 struct window *w;
9438 {
9439 struct frame *f = XFRAME (w->frame);
9440 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
9441 int hpos = w->phys_cursor.hpos;
9442 int vpos = w->phys_cursor.vpos;
9443 int mouse_face_here_p = 0;
9444 struct glyph_matrix *active_glyphs = w->current_matrix;
9445 struct glyph_row *cursor_row;
9446 struct glyph *cursor_glyph;
9447 enum draw_glyphs_face hl;
9448
9449 /* No cursor displayed or row invalidated => nothing to do on the
9450 screen. */
9451 if (w->phys_cursor_type == NO_CURSOR)
9452 goto mark_cursor_off;
9453
9454 /* VPOS >= active_glyphs->nrows means that window has been resized.
9455 Don't bother to erase the cursor. */
9456 if (vpos >= active_glyphs->nrows)
9457 goto mark_cursor_off;
9458
9459 /* If row containing cursor is marked invalid, there is nothing we
9460 can do. */
9461 cursor_row = MATRIX_ROW (active_glyphs, vpos);
9462 if (!cursor_row->enabled_p)
9463 goto mark_cursor_off;
9464
9465 /* This can happen when the new row is shorter than the old one.
9466 In this case, either x_draw_glyphs or clear_end_of_line
9467 should have cleared the cursor. Note that we wouldn't be
9468 able to erase the cursor in this case because we don't have a
9469 cursor glyph at hand. */
9470 if (w->phys_cursor.hpos >= cursor_row->used[TEXT_AREA])
9471 goto mark_cursor_off;
9472
9473 /* If the cursor is in the mouse face area, redisplay that when
9474 we clear the cursor. */
9475 if (! NILP (dpyinfo->mouse_face_window)
9476 && w == XWINDOW (dpyinfo->mouse_face_window)
9477 && (vpos > dpyinfo->mouse_face_beg_row
9478 || (vpos == dpyinfo->mouse_face_beg_row
9479 && hpos >= dpyinfo->mouse_face_beg_col))
9480 && (vpos < dpyinfo->mouse_face_end_row
9481 || (vpos == dpyinfo->mouse_face_end_row
9482 && hpos < dpyinfo->mouse_face_end_col))
9483 /* Don't redraw the cursor's spot in mouse face if it is at the
9484 end of a line (on a newline). The cursor appears there, but
9485 mouse highlighting does not. */
9486 && cursor_row->used[TEXT_AREA] > hpos)
9487 mouse_face_here_p = 1;
9488
9489 /* Maybe clear the display under the cursor. */
9490 if (w->phys_cursor_type == HOLLOW_BOX_CURSOR)
9491 {
9492 int x;
9493 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
9494 HDC hdc;
9495
9496 cursor_glyph = get_phys_cursor_glyph (w);
9497 if (cursor_glyph == NULL)
9498 goto mark_cursor_off;
9499
9500 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9501
9502 hdc = get_frame_dc (f);
9503 w32_clear_area (f, hdc, x,
9504 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
9505 cursor_row->y)),
9506 cursor_glyph->pixel_width,
9507 cursor_row->visible_height);
9508 release_frame_dc (f, hdc);
9509 }
9510
9511 /* Erase the cursor by redrawing the character underneath it. */
9512 if (mouse_face_here_p)
9513 hl = DRAW_MOUSE_FACE;
9514 else
9515 hl = DRAW_NORMAL_TEXT;
9516 x_draw_phys_cursor_glyph (w, cursor_row, hl);
9517
9518 mark_cursor_off:
9519 w->phys_cursor_on_p = 0;
9520 w->phys_cursor_type = NO_CURSOR;
9521 }
9522
9523
9524 /* Non-zero if physical cursor of window W is within mouse face. */
9525
9526 static int
9527 cursor_in_mouse_face_p (w)
9528 struct window *w;
9529 {
9530 struct w32_display_info *dpyinfo
9531 = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
9532 int in_mouse_face = 0;
9533
9534 if (WINDOWP (dpyinfo->mouse_face_window)
9535 && XWINDOW (dpyinfo->mouse_face_window) == w)
9536 {
9537 int hpos = w->phys_cursor.hpos;
9538 int vpos = w->phys_cursor.vpos;
9539
9540 if (vpos >= dpyinfo->mouse_face_beg_row
9541 && vpos <= dpyinfo->mouse_face_end_row
9542 && (vpos > dpyinfo->mouse_face_beg_row
9543 || hpos >= dpyinfo->mouse_face_beg_col)
9544 && (vpos < dpyinfo->mouse_face_end_row
9545 || hpos < dpyinfo->mouse_face_end_col
9546 || dpyinfo->mouse_face_past_end))
9547 in_mouse_face = 1;
9548 }
9549
9550 return in_mouse_face;
9551 }
9552
9553
9554 /* Display or clear cursor of window W. If ON is zero, clear the
9555 cursor. If it is non-zero, display the cursor. If ON is nonzero,
9556 where to put the cursor is specified by HPOS, VPOS, X and Y. */
9557
9558 void
9559 x_display_and_set_cursor (w, on, hpos, vpos, x, y)
9560 struct window *w;
9561 int on, hpos, vpos, x, y;
9562 {
9563 struct frame *f = XFRAME (w->frame);
9564 int new_cursor_type;
9565 int new_cursor_width;
9566 struct glyph_matrix *current_glyphs;
9567 struct glyph_row *glyph_row;
9568 struct glyph *glyph;
9569 int cursor_non_selected;
9570 int active_cursor = 1;
9571
9572 /* This is pointless on invisible frames, and dangerous on garbaged
9573 windows and frames; in the latter case, the frame or window may
9574 be in the midst of changing its size, and x and y may be off the
9575 window. */
9576 if (! FRAME_VISIBLE_P (f)
9577 || FRAME_GARBAGED_P (f)
9578 || vpos >= w->current_matrix->nrows
9579 || hpos >= w->current_matrix->matrix_w)
9580 return;
9581
9582 /* If cursor is off and we want it off, return quickly. */
9583 if (!on && !w->phys_cursor_on_p)
9584 return;
9585
9586 current_glyphs = w->current_matrix;
9587 glyph_row = MATRIX_ROW (current_glyphs, vpos);
9588 glyph = glyph_row->glyphs[TEXT_AREA] + hpos;
9589
9590 /* If cursor row is not enabled, we don't really know where to
9591 display the cursor. */
9592 if (!glyph_row->enabled_p)
9593 {
9594 w->phys_cursor_on_p = 0;
9595 return;
9596 }
9597
9598 xassert (interrupt_input_blocked);
9599
9600 /* Set new_cursor_type to the cursor we want to be displayed. In a
9601 mini-buffer window, we want the cursor only to appear if we are
9602 reading input from this window. For the selected window, we want
9603 the cursor type given by the frame parameter. If explicitly
9604 marked off, draw no cursor. In all other cases, we want a hollow
9605 box cursor. */
9606 cursor_non_selected
9607 = !NILP (Fbuffer_local_value (Qcursor_in_non_selected_windows,
9608 w->buffer));
9609 new_cursor_width = -1;
9610 if (cursor_in_echo_area
9611 && FRAME_HAS_MINIBUF_P (f)
9612 && EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window))
9613 {
9614 if (w == XWINDOW (echo_area_window))
9615 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9616 else
9617 {
9618 if (cursor_non_selected)
9619 new_cursor_type = HOLLOW_BOX_CURSOR;
9620 else
9621 new_cursor_type = NO_CURSOR;
9622 active_cursor = 0;
9623 }
9624 }
9625 else
9626 {
9627 if (f != FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame
9628 || w != XWINDOW (f->selected_window))
9629 {
9630 active_cursor = 0;
9631
9632 if (MINI_WINDOW_P (w)
9633 || !cursor_non_selected
9634 || NILP (XBUFFER (w->buffer)->cursor_type))
9635 new_cursor_type = NO_CURSOR;
9636 else
9637 new_cursor_type = HOLLOW_BOX_CURSOR;
9638 }
9639 else if (w->cursor_off_p)
9640 new_cursor_type = NO_CURSOR;
9641 else
9642 {
9643 struct buffer *b = XBUFFER (w->buffer);
9644
9645 if (EQ (b->cursor_type, Qt))
9646 new_cursor_type = FRAME_DESIRED_CURSOR (f);
9647 else
9648 new_cursor_type = x_specified_cursor_type (b->cursor_type,
9649 &new_cursor_width);
9650 }
9651 }
9652
9653 /* If cursor is currently being shown and we don't want it to be or
9654 it is in the wrong place, or the cursor type is not what we want,
9655 erase it. */
9656 if (w->phys_cursor_on_p
9657 && (!on
9658 || w->phys_cursor.x != x
9659 || w->phys_cursor.y != y
9660 || new_cursor_type != w->phys_cursor_type))
9661 x_erase_phys_cursor (w);
9662
9663 /* If the cursor is now invisible and we want it to be visible,
9664 display it. */
9665 if (on && !w->phys_cursor_on_p)
9666 {
9667 w->phys_cursor_ascent = glyph_row->ascent;
9668 w->phys_cursor_height = glyph_row->height;
9669
9670 /* Set phys_cursor_.* before x_draw_.* is called because some
9671 of them may need the information. */
9672 w->phys_cursor.x = x;
9673 w->phys_cursor.y = glyph_row->y;
9674 w->phys_cursor.hpos = hpos;
9675 w->phys_cursor.vpos = vpos;
9676 w->phys_cursor_type = new_cursor_type;
9677 w->phys_cursor_on_p = 1;
9678
9679 /* If this is the active cursor, we need to track it with the
9680 system caret, so third party software like screen magnifiers
9681 and speech synthesizers can follow the cursor. */
9682 if (active_cursor)
9683 {
9684 struct glyph * cursor_glyph = get_phys_cursor_glyph (w);
9685 if (cursor_glyph)
9686 {
9687 HWND hwnd = FRAME_W32_WINDOW (f);
9688 int caret_width = cursor_glyph->pixel_width;
9689 w32_system_caret_x
9690 = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
9691 w32_system_caret_y
9692 = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
9693 + glyph_row->ascent - w->phys_cursor_ascent);
9694
9695 /* If the size of the active cursor changed, destroy the old
9696 system caret. */
9697 if (w32_system_caret_hwnd
9698 && (w32_system_caret_height != w->phys_cursor_height
9699 || w32_system_caret_width != caret_width))
9700 PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
9701
9702 if (!w32_system_caret_hwnd)
9703 {
9704 w32_system_caret_height = w->phys_cursor_height;
9705 w32_system_caret_width = caret_width;
9706 }
9707
9708 /* Move the system caret. */
9709 PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
9710 }
9711 }
9712
9713 switch (new_cursor_type)
9714 {
9715 case HOLLOW_BOX_CURSOR:
9716 x_draw_hollow_cursor (w, glyph_row);
9717 break;
9718
9719 case FILLED_BOX_CURSOR:
9720 x_draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
9721 break;
9722
9723 case BAR_CURSOR:
9724 x_draw_bar_cursor (w, glyph_row, new_cursor_width);
9725 break;
9726
9727 case NO_CURSOR:
9728 break;
9729
9730 default:
9731 abort ();
9732 }
9733 }
9734 }
9735
9736
9737 /* Display the cursor on window W, or clear it. X and Y are window
9738 relative pixel coordinates. HPOS and VPOS are glyph matrix
9739 positions. If W is not the selected window, display a hollow
9740 cursor. ON non-zero means display the cursor at X, Y which
9741 correspond to HPOS, VPOS, otherwise it is cleared. */
9742
9743 void
9744 x_display_cursor (w, on, hpos, vpos, x, y)
9745 struct window *w;
9746 int on, hpos, vpos, x, y;
9747 {
9748 BLOCK_INPUT;
9749 x_display_and_set_cursor (w, on, hpos, vpos, x, y);
9750 UNBLOCK_INPUT;
9751 }
9752
9753
9754 /* Display the cursor on window W, or clear it, according to ON_P.
9755 Don't change the cursor's position. */
9756
9757 void
9758 x_update_cursor (f, on_p)
9759 struct frame *f;
9760 int on_p;
9761 {
9762 x_update_cursor_in_window_tree (XWINDOW (f->root_window), on_p);
9763 }
9764
9765
9766 /* Call x_update_window_cursor with parameter ON_P on all leaf windows
9767 in the window tree rooted at W. */
9768
9769 static void
9770 x_update_cursor_in_window_tree (w, on_p)
9771 struct window *w;
9772 int on_p;
9773 {
9774 while (w)
9775 {
9776 if (!NILP (w->hchild))
9777 x_update_cursor_in_window_tree (XWINDOW (w->hchild), on_p);
9778 else if (!NILP (w->vchild))
9779 x_update_cursor_in_window_tree (XWINDOW (w->vchild), on_p);
9780 else
9781 x_update_window_cursor (w, on_p);
9782
9783 w = NILP (w->next) ? 0 : XWINDOW (w->next);
9784 }
9785 }
9786
9787
9788 /* Switch the display of W's cursor on or off, according to the value
9789 of ON. */
9790
9791 static void
9792 x_update_window_cursor (w, on)
9793 struct window *w;
9794 int on;
9795 {
9796 /* Don't update cursor in windows whose frame is in the process
9797 of being deleted. */
9798 if (w->current_matrix)
9799 {
9800 BLOCK_INPUT;
9801 x_display_and_set_cursor (w, on, w->phys_cursor.hpos,
9802 w->phys_cursor.vpos, w->phys_cursor.x,
9803 w->phys_cursor.y);
9804 UNBLOCK_INPUT;
9805 }
9806 }
9807
9808
9809
9810 \f
9811 /* Icons. */
9812
9813 int
9814 x_bitmap_icon (f, icon)
9815 struct frame *f;
9816 Lisp_Object icon;
9817 {
9818 HANDLE hicon;
9819
9820 if (FRAME_W32_WINDOW (f) == 0)
9821 return 1;
9822
9823 if (NILP (icon))
9824 hicon = LoadIcon (hinst, EMACS_CLASS);
9825 else if (STRINGP (icon))
9826 hicon = LoadImage (NULL, (LPCTSTR) XSTRING (icon)->data, IMAGE_ICON, 0, 0,
9827 LR_DEFAULTSIZE | LR_LOADFROMFILE);
9828 else if (SYMBOLP (icon))
9829 {
9830 LPCTSTR name;
9831
9832 if (EQ (icon, intern ("application")))
9833 name = (LPCTSTR) IDI_APPLICATION;
9834 else if (EQ (icon, intern ("hand")))
9835 name = (LPCTSTR) IDI_HAND;
9836 else if (EQ (icon, intern ("question")))
9837 name = (LPCTSTR) IDI_QUESTION;
9838 else if (EQ (icon, intern ("exclamation")))
9839 name = (LPCTSTR) IDI_EXCLAMATION;
9840 else if (EQ (icon, intern ("asterisk")))
9841 name = (LPCTSTR) IDI_ASTERISK;
9842 else if (EQ (icon, intern ("winlogo")))
9843 name = (LPCTSTR) IDI_WINLOGO;
9844 else
9845 return 1;
9846
9847 hicon = LoadIcon (NULL, name);
9848 }
9849 else
9850 return 1;
9851
9852 if (hicon == NULL)
9853 return 1;
9854
9855 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
9856 (LPARAM) hicon);
9857
9858 return 0;
9859 }
9860
9861 \f
9862 /************************************************************************
9863 Handling X errors
9864 ************************************************************************/
9865
9866 /* Display Error Handling functions not used on W32. Listing them here
9867 helps diff stay in step when comparing w32term.c with xterm.c.
9868
9869 x_error_catcher (display, error)
9870 x_catch_errors (dpy)
9871 x_catch_errors_unwind (old_val)
9872 x_check_errors (dpy, format)
9873 x_had_errors_p (dpy)
9874 x_clear_errors (dpy)
9875 x_uncatch_errors (dpy, count)
9876 x_trace_wire ()
9877 x_connection_signal (signalnum)
9878 x_connection_closed (dpy, error_message)
9879 x_error_quitter (display, error)
9880 x_error_handler (display, error)
9881 x_io_error_quitter (display)
9882
9883 */
9884
9885 \f
9886 /* Changing the font of the frame. */
9887
9888 /* Give frame F the font named FONTNAME as its default font, and
9889 return the full name of that font. FONTNAME may be a wildcard
9890 pattern; in that case, we choose some font that fits the pattern.
9891 The return value shows which font we chose. */
9892
9893 Lisp_Object
9894 x_new_font (f, fontname)
9895 struct frame *f;
9896 register char *fontname;
9897 {
9898 struct font_info *fontp
9899 = FS_LOAD_FONT (f, 0, fontname, -1);
9900
9901 if (!fontp)
9902 return Qnil;
9903
9904 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
9905 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
9906 FRAME_FONTSET (f) = -1;
9907
9908 /* Compute the scroll bar width in character columns. */
9909 if (f->scroll_bar_pixel_width > 0)
9910 {
9911 int wid = FONT_WIDTH (FRAME_FONT (f));
9912 f->scroll_bar_cols = (f->scroll_bar_pixel_width + wid-1) / wid;
9913 }
9914 else
9915 {
9916 int wid = FONT_WIDTH (FRAME_FONT (f));
9917 f->scroll_bar_cols = (14 + wid - 1) / wid;
9918 }
9919
9920 /* Now make the frame display the given font. */
9921 if (FRAME_W32_WINDOW (f) != 0)
9922 {
9923 frame_update_line_height (f);
9924 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
9925 x_set_window_size (f, 0, f->width, f->height);
9926 }
9927 else
9928 /* If we are setting a new frame's font for the first time,
9929 there are no faces yet, so this font's height is the line height. */
9930 f->output_data.w32->line_height = FONT_HEIGHT (FRAME_FONT (f));
9931
9932 return build_string (fontp->full_name);
9933 }
9934 \f
9935 /* Give frame F the fontset named FONTSETNAME as its default font, and
9936 return the full name of that fontset. FONTSETNAME may be a wildcard
9937 pattern; in that case, we choose some fontset that fits the pattern.
9938 The return value shows which fontset we chose. */
9939
9940 Lisp_Object
9941 x_new_fontset (f, fontsetname)
9942 struct frame *f;
9943 char *fontsetname;
9944 {
9945 int fontset = fs_query_fontset (build_string (fontsetname), 0);
9946 Lisp_Object result;
9947
9948 if (fontset < 0)
9949 return Qnil;
9950
9951 if (FRAME_FONTSET (f) == fontset)
9952 /* This fontset is already set in frame F. There's nothing more
9953 to do. */
9954 return fontset_name (fontset);
9955
9956 result = x_new_font (f, (XSTRING (fontset_ascii (fontset))->data));
9957
9958 if (!STRINGP (result))
9959 /* Can't load ASCII font. */
9960 return Qnil;
9961
9962 /* Since x_new_font doesn't update any fontset information, do it now. */
9963 FRAME_FONTSET(f) = fontset;
9964
9965 return build_string (fontsetname);
9966 }
9967
9968 /* Compute actual fringe widths */
9969
9970 void
9971 x_compute_fringe_widths (f, redraw)
9972 struct frame *f;
9973 int redraw;
9974 {
9975 int o_left = f->output_data.w32->left_fringe_width;
9976 int o_right = f->output_data.w32->right_fringe_width;
9977 int o_cols = f->output_data.w32->fringe_cols;
9978
9979 Lisp_Object left_fringe = Fassq (Qleft_fringe, f->param_alist);
9980 Lisp_Object right_fringe = Fassq (Qright_fringe, f->param_alist);
9981 int left_fringe_width, right_fringe_width;
9982
9983 if (!NILP (left_fringe))
9984 left_fringe = Fcdr (left_fringe);
9985 if (!NILP (right_fringe))
9986 right_fringe = Fcdr (right_fringe);
9987
9988 left_fringe_width = ((NILP (left_fringe) || !INTEGERP (left_fringe)) ? 8 :
9989 XINT (left_fringe));
9990 right_fringe_width = ((NILP (right_fringe) || !INTEGERP (right_fringe)) ? 8 :
9991 XINT (right_fringe));
9992
9993 if (left_fringe_width || right_fringe_width)
9994 {
9995 int left_wid = left_fringe_width >= 0 ? left_fringe_width : -left_fringe_width;
9996 int right_wid = right_fringe_width >= 0 ? right_fringe_width : -right_fringe_width;
9997 int conf_wid = left_wid + right_wid;
9998 int font_wid = FONT_WIDTH (f->output_data.w32->font);
9999 int cols = (left_wid + right_wid + font_wid-1) / font_wid;
10000 int real_wid = cols * font_wid;
10001 if (left_wid && right_wid)
10002 {
10003 if (left_fringe_width < 0)
10004 {
10005 /* Left fringe width is fixed, adjust right fringe if necessary */
10006 f->output_data.w32->left_fringe_width = left_wid;
10007 f->output_data.w32->right_fringe_width = real_wid - left_wid;
10008 }
10009 else if (right_fringe_width < 0)
10010 {
10011 /* Right fringe width is fixed, adjust left fringe if necessary */
10012 f->output_data.w32->left_fringe_width = real_wid - right_wid;
10013 f->output_data.w32->right_fringe_width = right_wid;
10014 }
10015 else
10016 {
10017 /* Adjust both fringes with an equal amount.
10018 Note that we are doing integer arithmetic here, so don't
10019 lose a pixel if the total width is an odd number. */
10020 int fill = real_wid - conf_wid;
10021 f->output_data.w32->left_fringe_width = left_wid + fill/2;
10022 f->output_data.w32->right_fringe_width = right_wid + fill - fill/2;
10023 }
10024 }
10025 else if (left_fringe_width)
10026 {
10027 f->output_data.w32->left_fringe_width = real_wid;
10028 f->output_data.w32->right_fringe_width = 0;
10029 }
10030 else
10031 {
10032 f->output_data.w32->left_fringe_width = 0;
10033 f->output_data.w32->right_fringe_width = real_wid;
10034 }
10035 f->output_data.w32->fringe_cols = cols;
10036 f->output_data.w32->fringes_extra = real_wid;
10037 }
10038 else
10039 {
10040 f->output_data.w32->left_fringe_width = 0;
10041 f->output_data.w32->right_fringe_width = 0;
10042 f->output_data.w32->fringe_cols = 0;
10043 f->output_data.w32->fringes_extra = 0;
10044 }
10045
10046 if (redraw && FRAME_VISIBLE_P (f))
10047 if (o_left != f->output_data.w32->left_fringe_width ||
10048 o_right != f->output_data.w32->right_fringe_width ||
10049 o_cols != f->output_data.w32->fringe_cols)
10050 redraw_frame (f);
10051 }
10052 \f
10053 /***********************************************************************
10054 TODO: W32 Input Methods
10055 ***********************************************************************/
10056 /* Listing missing functions from xterm.c helps diff stay in step.
10057
10058 xim_destroy_callback (xim, client_data, call_data)
10059 xim_open_dpy (dpyinfo, resource_name)
10060 struct xim_inst_t
10061 xim_instantiate_callback (display, client_data, call_data)
10062 xim_initialize (dpyinfo, resource_name)
10063 xim_close_dpy (dpyinfo)
10064
10065 */
10066
10067 \f
10068 /* Calculate the absolute position in frame F
10069 from its current recorded position values and gravity. */
10070
10071 void
10072 x_calc_absolute_position (f)
10073 struct frame *f;
10074 {
10075 POINT pt;
10076 int flags = f->output_data.w32->size_hint_flags;
10077
10078 pt.x = pt.y = 0;
10079
10080 /* Find the position of the outside upper-left corner of
10081 the inner window, with respect to the outer window.
10082 But do this only if we will need the results. */
10083 if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
10084 {
10085 BLOCK_INPUT;
10086 MapWindowPoints (FRAME_W32_WINDOW (f),
10087 f->output_data.w32->parent_desc,
10088 &pt, 1);
10089 UNBLOCK_INPUT;
10090 }
10091
10092 {
10093 RECT rt;
10094 rt.left = rt.right = rt.top = rt.bottom = 0;
10095
10096 BLOCK_INPUT;
10097 AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
10098 FRAME_EXTERNAL_MENU_BAR (f));
10099 UNBLOCK_INPUT;
10100
10101 pt.x += (rt.right - rt.left);
10102 pt.y += (rt.bottom - rt.top);
10103 }
10104
10105 /* Treat negative positions as relative to the leftmost bottommost
10106 position that fits on the screen. */
10107 if (flags & XNegative)
10108 f->output_data.w32->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
10109 - 2 * f->output_data.w32->border_width - pt.x
10110 - PIXEL_WIDTH (f)
10111 + f->output_data.w32->left_pos);
10112
10113 if (flags & YNegative)
10114 f->output_data.w32->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
10115 - 2 * f->output_data.w32->border_width - pt.y
10116 - PIXEL_HEIGHT (f)
10117 + f->output_data.w32->top_pos);
10118 /* The left_pos and top_pos
10119 are now relative to the top and left screen edges,
10120 so the flags should correspond. */
10121 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
10122 }
10123
10124 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
10125 to really change the position, and 0 when calling from
10126 x_make_frame_visible (in that case, XOFF and YOFF are the current
10127 position values). It is -1 when calling from x_set_frame_parameters,
10128 which means, do adjust for borders but don't change the gravity. */
10129
10130 void
10131 x_set_offset (f, xoff, yoff, change_gravity)
10132 struct frame *f;
10133 register int xoff, yoff;
10134 int change_gravity;
10135 {
10136 int modified_top, modified_left;
10137
10138 if (change_gravity > 0)
10139 {
10140 f->output_data.w32->top_pos = yoff;
10141 f->output_data.w32->left_pos = xoff;
10142 f->output_data.w32->size_hint_flags &= ~ (XNegative | YNegative);
10143 if (xoff < 0)
10144 f->output_data.w32->size_hint_flags |= XNegative;
10145 if (yoff < 0)
10146 f->output_data.w32->size_hint_flags |= YNegative;
10147 f->output_data.w32->win_gravity = NorthWestGravity;
10148 }
10149 x_calc_absolute_position (f);
10150
10151 BLOCK_INPUT;
10152 x_wm_set_size_hint (f, (long) 0, 0);
10153
10154 modified_left = f->output_data.w32->left_pos;
10155 modified_top = f->output_data.w32->top_pos;
10156
10157 my_set_window_pos (FRAME_W32_WINDOW (f),
10158 NULL,
10159 modified_left, modified_top,
10160 0, 0,
10161 SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
10162 UNBLOCK_INPUT;
10163 }
10164
10165 /* Call this to change the size of frame F's x-window.
10166 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
10167 for this size change and subsequent size changes.
10168 Otherwise we leave the window gravity unchanged. */
10169
10170 void
10171 x_set_window_size (f, change_gravity, cols, rows)
10172 struct frame *f;
10173 int change_gravity;
10174 int cols, rows;
10175 {
10176 int pixelwidth, pixelheight;
10177
10178 BLOCK_INPUT;
10179
10180 check_frame_size (f, &rows, &cols);
10181 f->output_data.w32->vertical_scroll_bar_extra
10182 = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
10183 ? 0
10184 : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.w32->font)));
10185
10186 x_compute_fringe_widths (f, 0);
10187
10188 pixelwidth = CHAR_TO_PIXEL_WIDTH (f, cols);
10189 pixelheight = CHAR_TO_PIXEL_HEIGHT (f, rows);
10190
10191 f->output_data.w32->win_gravity = NorthWestGravity;
10192 x_wm_set_size_hint (f, (long) 0, 0);
10193
10194 {
10195 RECT rect;
10196
10197 rect.left = rect.top = 0;
10198 rect.right = pixelwidth;
10199 rect.bottom = pixelheight;
10200
10201 AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
10202 FRAME_EXTERNAL_MENU_BAR (f));
10203
10204 my_set_window_pos (FRAME_W32_WINDOW (f),
10205 NULL,
10206 0, 0,
10207 rect.right - rect.left,
10208 rect.bottom - rect.top,
10209 SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
10210 }
10211
10212 /* Now, strictly speaking, we can't be sure that this is accurate,
10213 but the window manager will get around to dealing with the size
10214 change request eventually, and we'll hear how it went when the
10215 ConfigureNotify event gets here.
10216
10217 We could just not bother storing any of this information here,
10218 and let the ConfigureNotify event set everything up, but that
10219 might be kind of confusing to the Lisp code, since size changes
10220 wouldn't be reported in the frame parameters until some random
10221 point in the future when the ConfigureNotify event arrives.
10222
10223 We pass 1 for DELAY since we can't run Lisp code inside of
10224 a BLOCK_INPUT. */
10225 change_frame_size (f, rows, cols, 0, 1, 0);
10226 PIXEL_WIDTH (f) = pixelwidth;
10227 PIXEL_HEIGHT (f) = pixelheight;
10228
10229 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
10230 receive in the ConfigureNotify event; if we get what we asked
10231 for, then the event won't cause the screen to become garbaged, so
10232 we have to make sure to do it here. */
10233 SET_FRAME_GARBAGED (f);
10234
10235 /* If cursor was outside the new size, mark it as off. */
10236 mark_window_cursors_off (XWINDOW (f->root_window));
10237
10238 /* Clear out any recollection of where the mouse highlighting was,
10239 since it might be in a place that's outside the new frame size.
10240 Actually checking whether it is outside is a pain in the neck,
10241 so don't try--just let the highlighting be done afresh with new size. */
10242 cancel_mouse_face (f);
10243
10244 UNBLOCK_INPUT;
10245 }
10246 \f
10247 /* Mouse warping. */
10248
10249 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
10250
10251 void
10252 x_set_mouse_position (f, x, y)
10253 struct frame *f;
10254 int x, y;
10255 {
10256 int pix_x, pix_y;
10257
10258 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->output_data.w32->font) / 2;
10259 pix_y = CHAR_TO_PIXEL_ROW (f, y) + f->output_data.w32->line_height / 2;
10260
10261 if (pix_x < 0) pix_x = 0;
10262 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f);
10263
10264 if (pix_y < 0) pix_y = 0;
10265 if (pix_y > PIXEL_HEIGHT (f)) pix_y = PIXEL_HEIGHT (f);
10266
10267 x_set_mouse_pixel_position (f, pix_x, pix_y);
10268 }
10269
10270 void
10271 x_set_mouse_pixel_position (f, pix_x, pix_y)
10272 struct frame *f;
10273 int pix_x, pix_y;
10274 {
10275 RECT rect;
10276 POINT pt;
10277
10278 BLOCK_INPUT;
10279
10280 GetClientRect (FRAME_W32_WINDOW (f), &rect);
10281 pt.x = rect.left + pix_x;
10282 pt.y = rect.top + pix_y;
10283 ClientToScreen (FRAME_W32_WINDOW (f), &pt);
10284
10285 SetCursorPos (pt.x, pt.y);
10286
10287 UNBLOCK_INPUT;
10288 }
10289
10290 \f
10291 /* focus shifting, raising and lowering. */
10292
10293 void
10294 x_focus_on_frame (f)
10295 struct frame *f;
10296 {
10297 struct w32_display_info *dpyinfo = &one_w32_display_info;
10298
10299 /* Give input focus to frame. */
10300 BLOCK_INPUT;
10301 #if 0
10302 /* Try not to change its Z-order if possible. */
10303 if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
10304 my_set_focus (f, FRAME_W32_WINDOW (f));
10305 else
10306 #endif
10307 my_set_foreground_window (FRAME_W32_WINDOW (f));
10308 UNBLOCK_INPUT;
10309 }
10310
10311 void
10312 x_unfocus_frame (f)
10313 struct frame *f;
10314 {
10315 }
10316
10317 /* Raise frame F. */
10318 void
10319 x_raise_frame (f)
10320 struct frame *f;
10321 {
10322 BLOCK_INPUT;
10323
10324 /* Strictly speaking, raise-frame should only change the frame's Z
10325 order, leaving input focus unchanged. This is reasonable behaviour
10326 on X where the usual policy is point-to-focus. However, this
10327 behaviour would be very odd on Windows where the usual policy is
10328 click-to-focus.
10329
10330 On X, if the mouse happens to be over the raised frame, it gets
10331 input focus anyway (so the window with focus will never be
10332 completely obscured) - if not, then just moving the mouse over it
10333 is sufficient to give it focus. On Windows, the user must actually
10334 click on the frame (preferrably the title bar so as not to move
10335 point), which is more awkward. Also, no other Windows program
10336 raises a window to the top but leaves another window (possibly now
10337 completely obscured) with input focus.
10338
10339 Because there is a system setting on Windows that allows the user
10340 to choose the point to focus policy, we make the strict semantics
10341 optional, but by default we grab focus when raising. */
10342
10343 if (NILP (Vw32_grab_focus_on_raise))
10344 {
10345 /* The obvious call to my_set_window_pos doesn't work if Emacs is
10346 not already the foreground application: the frame is raised
10347 above all other frames belonging to us, but not above the
10348 current top window. To achieve that, we have to resort to this
10349 more cumbersome method. */
10350
10351 HDWP handle = BeginDeferWindowPos (2);
10352 if (handle)
10353 {
10354 DeferWindowPos (handle,
10355 FRAME_W32_WINDOW (f),
10356 HWND_TOP,
10357 0, 0, 0, 0,
10358 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10359
10360 DeferWindowPos (handle,
10361 GetForegroundWindow (),
10362 FRAME_W32_WINDOW (f),
10363 0, 0, 0, 0,
10364 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10365
10366 EndDeferWindowPos (handle);
10367 }
10368 }
10369 else
10370 {
10371 my_set_foreground_window (FRAME_W32_WINDOW (f));
10372 }
10373
10374 UNBLOCK_INPUT;
10375 }
10376
10377 /* Lower frame F. */
10378 void
10379 x_lower_frame (f)
10380 struct frame *f;
10381 {
10382 BLOCK_INPUT;
10383 my_set_window_pos (FRAME_W32_WINDOW (f),
10384 HWND_BOTTOM,
10385 0, 0, 0, 0,
10386 SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
10387 UNBLOCK_INPUT;
10388 }
10389
10390 static void
10391 w32_frame_raise_lower (f, raise_flag)
10392 FRAME_PTR f;
10393 int raise_flag;
10394 {
10395 if (! FRAME_W32_P (f))
10396 return;
10397
10398 if (raise_flag)
10399 x_raise_frame (f);
10400 else
10401 x_lower_frame (f);
10402 }
10403 \f
10404 /* Change of visibility. */
10405
10406 /* This tries to wait until the frame is really visible.
10407 However, if the window manager asks the user where to position
10408 the frame, this will return before the user finishes doing that.
10409 The frame will not actually be visible at that time,
10410 but it will become visible later when the window manager
10411 finishes with it. */
10412
10413 void
10414 x_make_frame_visible (f)
10415 struct frame *f;
10416 {
10417 Lisp_Object type;
10418
10419 BLOCK_INPUT;
10420
10421 type = x_icon_type (f);
10422 if (!NILP (type))
10423 x_bitmap_icon (f, type);
10424
10425 if (! FRAME_VISIBLE_P (f))
10426 {
10427 /* We test FRAME_GARBAGED_P here to make sure we don't
10428 call x_set_offset a second time
10429 if we get to x_make_frame_visible a second time
10430 before the window gets really visible. */
10431 if (! FRAME_ICONIFIED_P (f)
10432 && ! f->output_data.w32->asked_for_visible)
10433 x_set_offset (f, f->output_data.w32->left_pos, f->output_data.w32->top_pos, 0);
10434
10435 f->output_data.w32->asked_for_visible = 1;
10436
10437 // my_show_window (f, FRAME_W32_WINDOW (f), f->async_iconified ? SW_RESTORE : SW_SHOW);
10438 my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
10439 }
10440
10441 /* Synchronize to ensure Emacs knows the frame is visible
10442 before we do anything else. We do this loop with input not blocked
10443 so that incoming events are handled. */
10444 {
10445 Lisp_Object frame;
10446 int count;
10447
10448 /* This must come after we set COUNT. */
10449 UNBLOCK_INPUT;
10450
10451 XSETFRAME (frame, f);
10452
10453 /* Wait until the frame is visible. Process X events until a
10454 MapNotify event has been seen, or until we think we won't get a
10455 MapNotify at all.. */
10456 for (count = input_signal_count + 10;
10457 input_signal_count < count && !FRAME_VISIBLE_P (f);)
10458 {
10459 /* Force processing of queued events. */
10460 /* TODO: x_sync equivalent? */
10461
10462 /* Machines that do polling rather than SIGIO have been observed
10463 to go into a busy-wait here. So we'll fake an alarm signal
10464 to let the handler know that there's something to be read.
10465 We used to raise a real alarm, but it seems that the handler
10466 isn't always enabled here. This is probably a bug. */
10467 if (input_polling_used ())
10468 {
10469 /* It could be confusing if a real alarm arrives while processing
10470 the fake one. Turn it off and let the handler reset it. */
10471 int old_poll_suppress_count = poll_suppress_count;
10472 poll_suppress_count = 1;
10473 poll_for_input_1 ();
10474 poll_suppress_count = old_poll_suppress_count;
10475 }
10476 }
10477 FRAME_SAMPLE_VISIBILITY (f);
10478 }
10479 }
10480
10481 /* Change from mapped state to withdrawn state. */
10482
10483 /* Make the frame visible (mapped and not iconified). */
10484
10485 x_make_frame_invisible (f)
10486 struct frame *f;
10487 {
10488 /* Don't keep the highlight on an invisible frame. */
10489 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
10490 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
10491
10492 BLOCK_INPUT;
10493
10494 my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
10495
10496 /* We can't distinguish this from iconification
10497 just by the event that we get from the server.
10498 So we can't win using the usual strategy of letting
10499 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
10500 and synchronize with the server to make sure we agree. */
10501 f->visible = 0;
10502 FRAME_ICONIFIED_P (f) = 0;
10503 f->async_visible = 0;
10504 f->async_iconified = 0;
10505
10506 UNBLOCK_INPUT;
10507 }
10508
10509 /* Change window state from mapped to iconified. */
10510
10511 void
10512 x_iconify_frame (f)
10513 struct frame *f;
10514 {
10515 Lisp_Object type;
10516
10517 /* Don't keep the highlight on an invisible frame. */
10518 if (FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame == f)
10519 FRAME_W32_DISPLAY_INFO (f)->w32_highlight_frame = 0;
10520
10521 if (f->async_iconified)
10522 return;
10523
10524 BLOCK_INPUT;
10525
10526 type = x_icon_type (f);
10527 if (!NILP (type))
10528 x_bitmap_icon (f, type);
10529
10530 /* Simulate the user minimizing the frame. */
10531 SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
10532
10533 UNBLOCK_INPUT;
10534 }
10535
10536 \f
10537 /* Free X resources of frame F. */
10538
10539 void
10540 x_free_frame_resources (f)
10541 struct frame *f;
10542 {
10543 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10544
10545 BLOCK_INPUT;
10546
10547 if (FRAME_W32_WINDOW (f))
10548 my_destroy_window (f, FRAME_W32_WINDOW (f));
10549
10550 free_frame_menubar (f);
10551
10552 unload_color (f, f->output_data.x->foreground_pixel);
10553 unload_color (f, f->output_data.x->background_pixel);
10554 unload_color (f, f->output_data.w32->cursor_pixel);
10555 unload_color (f, f->output_data.w32->cursor_foreground_pixel);
10556 unload_color (f, f->output_data.w32->border_pixel);
10557 unload_color (f, f->output_data.w32->mouse_pixel);
10558 if (f->output_data.w32->white_relief.allocated_p)
10559 unload_color (f, f->output_data.w32->white_relief.pixel);
10560 if (f->output_data.w32->black_relief.allocated_p)
10561 unload_color (f, f->output_data.w32->black_relief.pixel);
10562
10563 if (FRAME_FACE_CACHE (f))
10564 free_frame_faces (f);
10565
10566 xfree (f->output_data.w32);
10567 f->output_data.w32 = NULL;
10568
10569 if (f == dpyinfo->w32_focus_frame)
10570 dpyinfo->w32_focus_frame = 0;
10571 if (f == dpyinfo->w32_focus_event_frame)
10572 dpyinfo->w32_focus_event_frame = 0;
10573 if (f == dpyinfo->w32_highlight_frame)
10574 dpyinfo->w32_highlight_frame = 0;
10575
10576 if (f == dpyinfo->mouse_face_mouse_frame)
10577 {
10578 dpyinfo->mouse_face_beg_row
10579 = dpyinfo->mouse_face_beg_col = -1;
10580 dpyinfo->mouse_face_end_row
10581 = dpyinfo->mouse_face_end_col = -1;
10582 dpyinfo->mouse_face_window = Qnil;
10583 dpyinfo->mouse_face_deferred_gc = 0;
10584 dpyinfo->mouse_face_mouse_frame = 0;
10585 }
10586
10587 UNBLOCK_INPUT;
10588 }
10589
10590
10591 /* Destroy the window of frame F. */
10592
10593 x_destroy_window (f)
10594 struct frame *f;
10595 {
10596 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10597
10598 x_free_frame_resources (f);
10599
10600 dpyinfo->reference_count--;
10601 }
10602
10603 \f
10604 /* Setting window manager hints. */
10605
10606 /* Set the normal size hints for the window manager, for frame F.
10607 FLAGS is the flags word to use--or 0 meaning preserve the flags
10608 that the window now has.
10609 If USER_POSITION is nonzero, we set the USPosition
10610 flag (this is useful when FLAGS is 0). */
10611 void
10612 x_wm_set_size_hint (f, flags, user_position)
10613 struct frame *f;
10614 long flags;
10615 int user_position;
10616 {
10617 Window window = FRAME_W32_WINDOW (f);
10618
10619 enter_crit ();
10620
10621 SetWindowLong (window, WND_FONTWIDTH_INDEX, FONT_WIDTH (f->output_data.w32->font));
10622 SetWindowLong (window, WND_LINEHEIGHT_INDEX, f->output_data.w32->line_height);
10623 SetWindowLong (window, WND_BORDER_INDEX, f->output_data.w32->internal_border_width);
10624 SetWindowLong (window, WND_SCROLLBAR_INDEX, f->output_data.w32->vertical_scroll_bar_extra);
10625
10626 leave_crit ();
10627 }
10628
10629 /* Window manager things */
10630 x_wm_set_icon_position (f, icon_x, icon_y)
10631 struct frame *f;
10632 int icon_x, icon_y;
10633 {
10634 #if 0
10635 Window window = FRAME_W32_WINDOW (f);
10636
10637 f->display.x->wm_hints.flags |= IconPositionHint;
10638 f->display.x->wm_hints.icon_x = icon_x;
10639 f->display.x->wm_hints.icon_y = icon_y;
10640
10641 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
10642 #endif
10643 }
10644
10645 \f
10646 /***********************************************************************
10647 Fonts
10648 ***********************************************************************/
10649
10650 /* The following functions are listed here to help diff stay in step
10651 with xterm.c. See w32fns.c for definitions.
10652
10653 x_get_font_info (f, font_idx)
10654 x_list_fonts (f, pattern, size, maxnames)
10655
10656 */
10657
10658 #if GLYPH_DEBUG
10659
10660 /* Check that FONT is valid on frame F. It is if it can be found in F's
10661 font table. */
10662
10663 static void
10664 x_check_font (f, font)
10665 struct frame *f;
10666 XFontStruct *font;
10667 {
10668 int i;
10669 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10670
10671 xassert (font != NULL);
10672
10673 for (i = 0; i < dpyinfo->n_fonts; i++)
10674 if (dpyinfo->font_table[i].name
10675 && font == dpyinfo->font_table[i].font)
10676 break;
10677
10678 xassert (i < dpyinfo->n_fonts);
10679 }
10680
10681 #endif /* GLYPH_DEBUG != 0 */
10682
10683 /* Set *W to the minimum width, *H to the minimum font height of FONT.
10684 Note: There are (broken) X fonts out there with invalid XFontStruct
10685 min_bounds contents. For example, handa@etl.go.jp reports that
10686 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
10687 have font->min_bounds.width == 0. */
10688
10689 static INLINE void
10690 x_font_min_bounds (font, w, h)
10691 XFontStruct *font;
10692 int *w, *h;
10693 {
10694 /*
10695 * TODO: Windows does not appear to offer min bound, only
10696 * average and maximum width, and maximum height.
10697 */
10698 *h = FONT_HEIGHT (font);
10699 *w = FONT_WIDTH (font);
10700 }
10701
10702
10703 /* Compute the smallest character width and smallest font height over
10704 all fonts available on frame F. Set the members smallest_char_width
10705 and smallest_font_height in F's x_display_info structure to
10706 the values computed. Value is non-zero if smallest_font_height or
10707 smallest_char_width become smaller than they were before. */
10708
10709 int
10710 x_compute_min_glyph_bounds (f)
10711 struct frame *f;
10712 {
10713 int i;
10714 struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
10715 XFontStruct *font;
10716 int old_width = dpyinfo->smallest_char_width;
10717 int old_height = dpyinfo->smallest_font_height;
10718
10719 dpyinfo->smallest_font_height = 100000;
10720 dpyinfo->smallest_char_width = 100000;
10721
10722 for (i = 0; i < dpyinfo->n_fonts; ++i)
10723 if (dpyinfo->font_table[i].name)
10724 {
10725 struct font_info *fontp = dpyinfo->font_table + i;
10726 int w, h;
10727
10728 font = (XFontStruct *) fontp->font;
10729 xassert (font != (XFontStruct *) ~0);
10730 x_font_min_bounds (font, &w, &h);
10731
10732 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
10733 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
10734 }
10735
10736 xassert (dpyinfo->smallest_char_width > 0
10737 && dpyinfo->smallest_font_height > 0);
10738
10739 return (dpyinfo->n_fonts == 1
10740 || dpyinfo->smallest_char_width < old_width
10741 || dpyinfo->smallest_font_height < old_height);
10742 }
10743
10744 /* The following functions are listed here to help diff stay in step
10745 with xterm.c. See w32fns.c for definitions.
10746
10747 x_load_font (f, fontname, size)
10748 x_query_font (f, fontname)
10749 x_find_ccl_program (fontp)
10750
10751 */
10752 \f
10753 /***********************************************************************
10754 Initialization
10755 ***********************************************************************/
10756
10757 static int w32_initialized = 0;
10758
10759 void
10760 w32_initialize_display_info (display_name)
10761 Lisp_Object display_name;
10762 {
10763 struct w32_display_info *dpyinfo = &one_w32_display_info;
10764
10765 bzero (dpyinfo, sizeof (*dpyinfo));
10766
10767 /* Put it on w32_display_name_list. */
10768 w32_display_name_list = Fcons (Fcons (display_name, Qnil),
10769 w32_display_name_list);
10770 dpyinfo->name_list_element = XCAR (w32_display_name_list);
10771
10772 dpyinfo->w32_id_name
10773 = (char *) xmalloc (XSTRING (Vinvocation_name)->size
10774 + XSTRING (Vsystem_name)->size
10775 + 2);
10776 sprintf (dpyinfo->w32_id_name, "%s@%s",
10777 XSTRING (Vinvocation_name)->data, XSTRING (Vsystem_name)->data);
10778
10779 /* Default Console mode values - overridden when running in GUI mode
10780 with values obtained from system metrics. */
10781 dpyinfo->resx = 1;
10782 dpyinfo->resy = 1;
10783 dpyinfo->height_in = 1;
10784 dpyinfo->width_in = 1;
10785 dpyinfo->n_planes = 1;
10786 dpyinfo->n_cbits = 4;
10787 dpyinfo->n_fonts = 0;
10788 dpyinfo->smallest_font_height = 1;
10789 dpyinfo->smallest_char_width = 1;
10790
10791 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
10792 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
10793 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
10794 dpyinfo->mouse_face_window = Qnil;
10795 dpyinfo->mouse_face_overlay = Qnil;
10796 /* TODO: dpyinfo->gray */
10797
10798 }
10799
10800 struct w32_display_info *
10801 w32_term_init (display_name, xrm_option, resource_name)
10802 Lisp_Object display_name;
10803 char *xrm_option;
10804 char *resource_name;
10805 {
10806 struct w32_display_info *dpyinfo;
10807 HDC hdc;
10808
10809 BLOCK_INPUT;
10810
10811 if (!w32_initialized)
10812 {
10813 w32_initialize ();
10814 w32_initialized = 1;
10815 }
10816
10817 {
10818 int argc = 0;
10819 char *argv[3];
10820
10821 argv[0] = "";
10822 argc = 1;
10823 if (xrm_option)
10824 {
10825 argv[argc++] = "-xrm";
10826 argv[argc++] = xrm_option;
10827 }
10828 }
10829
10830 w32_initialize_display_info (display_name);
10831
10832 dpyinfo = &one_w32_display_info;
10833
10834 /* Put this display on the chain. */
10835 dpyinfo->next = x_display_list;
10836 x_display_list = dpyinfo;
10837
10838 hdc = GetDC (GetDesktopWindow ());
10839
10840 dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
10841 dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
10842 dpyinfo->root_window = GetDesktopWindow ();
10843 dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
10844 dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
10845 dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
10846 dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
10847 dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
10848 dpyinfo->image_cache = make_image_cache ();
10849 dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
10850 dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
10851 ReleaseDC (GetDesktopWindow (), hdc);
10852
10853 /* initialise palette with white and black */
10854 {
10855 COLORREF color;
10856 w32_defined_color (0, "white", &color, 1);
10857 w32_defined_color (0, "black", &color, 1);
10858 }
10859
10860 /* Create Row Bitmaps and store them for later use. */
10861 left_bmp = CreateBitmap (left_width, left_height, 1, 1, left_bits);
10862 ov_bmp = CreateBitmap (ov_width, ov_height, 1, 1, ov_bits);
10863 right_bmp = CreateBitmap (right_width, right_height, 1, 1, right_bits);
10864 continued_bmp = CreateBitmap (continued_width, continued_height, 1,
10865 1, continued_bits);
10866 continuation_bmp = CreateBitmap (continuation_width, continuation_height,
10867 1, 1, continuation_bits);
10868 zv_bmp = CreateBitmap (zv_width, zv_height, 1, 1, zv_bits);
10869
10870 #ifndef F_SETOWN_BUG
10871 #ifdef F_SETOWN
10872 #ifdef F_SETOWN_SOCK_NEG
10873 /* stdin is a socket here */
10874 fcntl (connection, F_SETOWN, -getpid ());
10875 #else /* ! defined (F_SETOWN_SOCK_NEG) */
10876 fcntl (connection, F_SETOWN, getpid ());
10877 #endif /* ! defined (F_SETOWN_SOCK_NEG) */
10878 #endif /* ! defined (F_SETOWN) */
10879 #endif /* F_SETOWN_BUG */
10880
10881 #ifdef SIGIO
10882 if (interrupt_input)
10883 init_sigio (connection);
10884 #endif /* ! defined (SIGIO) */
10885
10886 UNBLOCK_INPUT;
10887
10888 return dpyinfo;
10889 }
10890 \f
10891 /* Get rid of display DPYINFO, assuming all frames are already gone. */
10892
10893 void
10894 x_delete_display (dpyinfo)
10895 struct w32_display_info *dpyinfo;
10896 {
10897 /* Discard this display from w32_display_name_list and w32_display_list.
10898 We can't use Fdelq because that can quit. */
10899 if (! NILP (w32_display_name_list)
10900 && EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
10901 w32_display_name_list = XCDR (w32_display_name_list);
10902 else
10903 {
10904 Lisp_Object tail;
10905
10906 tail = w32_display_name_list;
10907 while (CONSP (tail) && CONSP (XCDR (tail)))
10908 {
10909 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
10910 {
10911 XSETCDR (tail, XCDR (XCDR (tail)));
10912 break;
10913 }
10914 tail = XCDR (tail);
10915 }
10916 }
10917
10918 /* free palette table */
10919 {
10920 struct w32_palette_entry * plist;
10921
10922 plist = dpyinfo->color_list;
10923 while (plist)
10924 {
10925 struct w32_palette_entry * pentry = plist;
10926 plist = plist->next;
10927 xfree (pentry);
10928 }
10929 dpyinfo->color_list = NULL;
10930 if (dpyinfo->palette)
10931 DeleteObject(dpyinfo->palette);
10932 }
10933 xfree (dpyinfo->font_table);
10934 xfree (dpyinfo->w32_id_name);
10935
10936 /* Destroy row bitmaps. */
10937 DeleteObject (left_bmp);
10938 DeleteObject (ov_bmp);
10939 DeleteObject (right_bmp);
10940 DeleteObject (continued_bmp);
10941 DeleteObject (continuation_bmp);
10942 DeleteObject (zv_bmp);
10943 }
10944 \f
10945 /* Set up use of W32. */
10946
10947 DWORD w32_msg_worker ();
10948
10949 void
10950 x_flush (struct frame * f)
10951 { /* Nothing to do */ }
10952
10953 static struct redisplay_interface w32_redisplay_interface =
10954 {
10955 x_produce_glyphs,
10956 x_write_glyphs,
10957 x_insert_glyphs,
10958 x_clear_end_of_line,
10959 x_scroll_run,
10960 x_after_update_window_line,
10961 x_update_window_begin,
10962 x_update_window_end,
10963 w32_cursor_to,
10964 x_flush,
10965 x_clear_mouse_face,
10966 x_get_glyph_overhangs,
10967 x_fix_overlapping_area
10968 };
10969
10970 void
10971 w32_initialize ()
10972 {
10973 rif = &w32_redisplay_interface;
10974
10975 /* MSVC does not type K&R functions with no arguments correctly, and
10976 so we must explicitly cast them. */
10977 clear_frame_hook = (void (*)(void)) x_clear_frame;
10978 ring_bell_hook = (void (*)(void)) w32_ring_bell;
10979 update_begin_hook = x_update_begin;
10980 update_end_hook = x_update_end;
10981
10982 read_socket_hook = w32_read_socket;
10983
10984 frame_up_to_date_hook = w32_frame_up_to_date;
10985
10986 mouse_position_hook = w32_mouse_position;
10987 frame_rehighlight_hook = w32_frame_rehighlight;
10988 frame_raise_lower_hook = w32_frame_raise_lower;
10989 set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
10990 condemn_scroll_bars_hook = w32_condemn_scroll_bars;
10991 redeem_scroll_bar_hook = w32_redeem_scroll_bar;
10992 judge_scroll_bars_hook = w32_judge_scroll_bars;
10993 estimate_mode_line_height_hook = x_estimate_mode_line_height;
10994
10995 scroll_region_ok = 1; /* we'll scroll partial frames */
10996 char_ins_del_ok = 1;
10997 line_ins_del_ok = 1; /* we'll just blt 'em */
10998 fast_clear_end_of_line = 1; /* X does this well */
10999 memory_below_frame = 0; /* we don't remember what scrolls
11000 off the bottom */
11001 baud_rate = 19200;
11002
11003 w32_system_caret_hwnd = NULL;
11004 w32_system_caret_height = 0;
11005 w32_system_caret_width = 0;
11006 w32_system_caret_x = 0;
11007 w32_system_caret_y = 0;
11008
11009 last_tool_bar_item = -1;
11010 any_help_event_p = 0;
11011
11012 /* Initialize input mode: interrupt_input off, no flow control, allow
11013 8 bit character input, standard quit char. */
11014 Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
11015
11016 /* Create the window thread - it will terminate itself or when the app terminates */
11017
11018 init_crit ();
11019
11020 dwMainThreadId = GetCurrentThreadId ();
11021 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
11022 GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
11023
11024 /* Wait for thread to start */
11025
11026 {
11027 MSG msg;
11028
11029 PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
11030
11031 hWindowsThread = CreateThread (NULL, 0,
11032 (LPTHREAD_START_ROUTINE) w32_msg_worker,
11033 0, 0, &dwWindowsThreadId);
11034
11035 GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
11036 }
11037
11038 /* It is desirable that mainThread should have the same notion of
11039 focus window and active window as windowsThread. Unfortunately, the
11040 following call to AttachThreadInput, which should do precisely what
11041 we need, causes major problems when Emacs is linked as a console
11042 program. Unfortunately, we have good reasons for doing that, so
11043 instead we need to send messages to windowsThread to make some API
11044 calls for us (ones that affect, or depend on, the active/focus
11045 window state. */
11046 #ifdef ATTACH_THREADS
11047 AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
11048 #endif
11049
11050 /* Dynamically link to optional system components. */
11051 {
11052 HANDLE user_lib = LoadLibrary ("user32.dll");
11053
11054 #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
11055
11056 /* New proportional scroll bar functions. */
11057 LOAD_PROC (SetScrollInfo);
11058 LOAD_PROC (GetScrollInfo);
11059
11060 #undef LOAD_PROC
11061
11062 FreeLibrary (user_lib);
11063
11064 /* If using proportional scroll bars, ensure handle is at least 5 pixels;
11065 otherwise use the fixed height. */
11066 vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
11067 GetSystemMetrics (SM_CYVTHUMB);
11068
11069 /* For either kind of scroll bar, take account of the arrows; these
11070 effectively form the border of the main scroll bar range. */
11071 vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
11072 = GetSystemMetrics (SM_CYVSCROLL);
11073 }
11074 }
11075
11076 void
11077 syms_of_w32term ()
11078 {
11079 staticpro (&w32_display_name_list);
11080 w32_display_name_list = Qnil;
11081
11082 staticpro (&last_mouse_scroll_bar);
11083 last_mouse_scroll_bar = Qnil;
11084
11085 staticpro (&Qvendor_specific_keysyms);
11086 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
11087
11088 DEFVAR_INT ("w32-num-mouse-buttons",
11089 &Vw32_num_mouse_buttons,
11090 doc: /* Number of physical mouse buttons. */);
11091 Vw32_num_mouse_buttons = Qnil;
11092
11093 DEFVAR_LISP ("w32-swap-mouse-buttons",
11094 &Vw32_swap_mouse_buttons,
11095 doc: /* Swap the mapping of middle and right mouse buttons.
11096 When nil, middle button is mouse-2 and right button is mouse-3. */);
11097 Vw32_swap_mouse_buttons = Qnil;
11098
11099 DEFVAR_LISP ("w32-grab-focus-on-raise",
11100 &Vw32_grab_focus_on_raise,
11101 doc: /* Raised frame grabs input focus.
11102 When t, `raise-frame' grabs input focus as well. This fits well
11103 with the normal Windows click-to-focus policy, but might not be
11104 desirable when using a point-to-focus policy. */);
11105 Vw32_grab_focus_on_raise = Qt;
11106
11107 DEFVAR_LISP ("w32-capslock-is-shiftlock",
11108 &Vw32_capslock_is_shiftlock,
11109 doc: /* Apply CapsLock state to non character input keys.
11110 When nil, CapsLock only affects normal character input keys. */);
11111 Vw32_capslock_is_shiftlock = Qnil;
11112
11113 DEFVAR_LISP ("w32-recognize-altgr",
11114 &Vw32_recognize_altgr,
11115 doc: /* Recognize right-alt and left-ctrl as AltGr.
11116 When nil, the right-alt and left-ctrl key combination is
11117 interpreted normally. */);
11118 Vw32_recognize_altgr = Qt;
11119
11120 DEFVAR_BOOL ("w32-enable-unicode-output",
11121 &w32_enable_unicode_output,
11122 doc: /* Enable the use of Unicode for text output if non-nil.
11123 Unicode output may prevent some third party applications for displaying
11124 Far-East Languages on Windows 95/98 from working properly.
11125 NT uses Unicode internally anyway, so this flag will probably have no
11126 affect on NT machines. */);
11127 w32_enable_unicode_output = 1;
11128
11129 help_echo = Qnil;
11130 staticpro (&help_echo);
11131 help_echo_object = Qnil;
11132 staticpro (&help_echo_object);
11133 help_echo_window = Qnil;
11134 staticpro (&help_echo_window);
11135 previous_help_echo = Qnil;
11136 staticpro (&previous_help_echo);
11137 help_echo_pos = -1;
11138
11139 DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
11140 doc: /* *Non-nil means draw block cursor as wide as the glyph under it.
11141 For example, if a block cursor is over a tab, it will be drawn as
11142 wide as that tab on the display. */);
11143 x_stretch_cursor_p = 0;
11144
11145 #if 0 /* TODO: Setting underline position from font properties. */
11146 DEFVAR_BOOL ("x-use-underline-position-properties",
11147 &x_use_underline_position_properties,
11148 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
11149 nil means ignore them. If you encounter fonts with bogus
11150 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
11151 to 4.1, set this to nil. */);
11152 x_use_underline_position_properties = 1;
11153 #endif
11154
11155 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
11156 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
11157 Vx_toolkit_scroll_bars = Qt;
11158
11159 staticpro (&last_mouse_motion_frame);
11160 last_mouse_motion_frame = Qnil;
11161 }