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