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