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