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