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