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