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