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