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