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