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