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