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