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