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