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