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