#include <config.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include "lisp.h"
#include "charset.h"
#include "blockinput.h"
#include "w32heap.h"
#include "w32term.h"
#include "w32bdf.h"
#include <shellapi.h>
#include "systty.h"
#include "systime.h"
#include "atimer.h"
#include "keymap.h"
#include <ctype.h>
#include <errno.h>
#include <setjmp.h>
#include <sys/stat.h>
#include "keyboard.h"
#include "frame.h"
#include "dispextern.h"
#include "fontset.h"
#include "termhooks.h"
#include "termopts.h"
#include "termchar.h"
#include "gnu.h"
#include "disptab.h"
#include "buffer.h"
#include "window.h"
#include "intervals.h"
#include "composite.h"
#include "coding.h"
#define abs(x) ((x) < 0 ? -(x) : (x))
static int max_fringe_bmp = 0;
static HBITMAP *fringe_bmp = 0;
Lisp_Object Vx_toolkit_scroll_bars;
static int last_mousemove_x = 0;
static int last_mousemove_y = 0;
#ifndef GET_WHEEL_DELTA_WPARAM
#define GET_WHEEL_DELTA_WPARAM(wparam) ((short)HIWORD (wparam))
#endif
static int any_help_event_p;
static Lisp_Object last_window;
int x_use_underline_position_properties;
int x_underline_at_descent_line;
extern unsigned int msh_mousewheel;
extern void free_frame_menubar ();
extern int w32_codepage_for_font (char *fontname);
extern Cursor w32_load_cursor (LPCTSTR name);
extern glyph_metric *w32_BDF_TextMetric(bdffont *fontp,
unsigned char *text, int dim);
extern Lisp_Object Vwindow_system;
#define x_any_window_to_frame x_window_to_frame
#define x_top_window_to_frame x_window_to_frame
struct w32_display_info one_w32_display_info;
struct w32_display_info *x_display_list;
Lisp_Object w32_display_name_list;
extern struct frame *updating_frame;
struct frame *pending_autoraise_frame;
HWND w32_system_caret_hwnd;
int w32_system_caret_height;
int w32_system_caret_x;
int w32_system_caret_y;
int w32_use_visible_system_caret;
int w32_enable_unicode_output;
static int cleartype_active;
DWORD dwWindowsThreadId = 0;
HANDLE hWindowsThread = NULL;
DWORD dwMainThreadId = 0;
HANDLE hMainThread = NULL;
int vertical_scroll_bar_min_handle;
int vertical_scroll_bar_top_border;
int vertical_scroll_bar_bottom_border;
int last_scroll_bar_drag_pos;
static RECT last_mouse_glyph;
static FRAME_PTR last_mouse_glyph_frame;
static Lisp_Object last_mouse_press_frame;
int w32_num_mouse_buttons;
Lisp_Object Vw32_swap_mouse_buttons;
Lisp_Object Vw32_grab_focus_on_raise;
Lisp_Object Vw32_capslock_is_shiftlock;
Lisp_Object Vw32_recognize_altgr;
static Lisp_Object last_mouse_scroll_bar;
static int last_mouse_scroll_bar_pos;
static Time last_mouse_movement_time;
#ifdef __STDC__
static int volatile input_signal_count;
#else
static int input_signal_count;
#endif
extern Lisp_Object Vcommand_line_args, Vsystem_name;
#ifndef USE_CRT_DLL
extern int errno;
#endif
extern EMACS_INT extra_keyboard_modifiers;
static void x_update_window_end P_ ((struct window *, int, int));
void w32_delete_display P_ ((struct w32_display_info *));
static void w32_handle_tool_bar_click P_ ((struct frame *,
struct input_event *));
void w32_define_cursor P_ ((Window, Cursor));
void x_lower_frame P_ ((struct frame *));
void x_scroll_bar_clear P_ ((struct frame *));
void x_wm_set_size_hint P_ ((struct frame *, long, int));
void x_raise_frame P_ ((struct frame *));
void x_set_window_size P_ ((struct frame *, int, int, int));
void x_wm_set_window_state P_ ((struct frame *, int));
void x_wm_set_icon_pixmap P_ ((struct frame *, int));
void w32_initialize P_ ((void));
static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
int x_compute_min_glyph_bounds P_ ((struct frame *));
static void x_update_end P_ ((struct frame *));
static void w32_frame_up_to_date P_ ((struct frame *));
static void w32_set_terminal_modes P_ ((void));
static void w32_reset_terminal_modes P_ ((void));
static void x_clear_frame P_ ((void));
static void frame_highlight P_ ((struct frame *));
static void frame_unhighlight P_ ((struct frame *));
static void x_new_focus_frame P_ ((struct w32_display_info *,
struct frame *));
static void x_focus_changed P_ ((int, int, struct w32_display_info *,
struct frame *, struct input_event *));
static void w32_detect_focus_change P_ ((struct w32_display_info *,
W32Msg *, struct input_event *));
static void w32_frame_rehighlight P_ ((struct frame *));
static void x_frame_rehighlight P_ ((struct w32_display_info *));
static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
enum text_cursor_kinds));
static void w32_clip_to_row P_ ((struct window *, struct glyph_row *, int, HDC));
static BOOL my_show_window P_ ((struct frame *, HWND, int));
static void my_set_window_pos P_ ((HWND, HWND, int, int, int, int, UINT));
static void my_set_focus P_ ((struct frame *, HWND));
static void my_set_foreground_window P_ ((HWND));
static void my_destroy_window P_ ((struct frame *, HWND));
static Lisp_Object Qvendor_specific_keysyms;
#if 0
struct record
{
char *locus;
int type;
};
struct record event_record[100];
int event_record_index;
record_event (locus, type)
char *locus;
int type;
{
if (event_record_index == sizeof (event_record) / sizeof (struct record))
event_record_index = 0;
event_record[event_record_index].locus = locus;
event_record[event_record_index].type = type;
event_record_index++;
}
#endif
void
XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
XGCValues *xgcv)
{
if (mask & GCForeground)
gc->foreground = xgcv->foreground;
if (mask & GCBackground)
gc->background = xgcv->background;
if (mask & GCFont)
gc->font = xgcv->font;
}
XGCValues *XCreateGC (void * ignore, Window window, unsigned long mask,
XGCValues *xgcv)
{
XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
bzero (gc, sizeof (XGCValues));
XChangeGC (ignore, gc, mask, xgcv);
return gc;
}
void
XGetGCValues (void* ignore, XGCValues *gc,
unsigned long mask, XGCValues *xgcv)
{
XChangeGC (ignore, xgcv, mask, gc);
}
static void
w32_set_clip_rectangle (HDC hdc, RECT *rect)
{
if (rect)
{
HRGN clip_region = CreateRectRgnIndirect (rect);
SelectClipRgn (hdc, clip_region);
DeleteObject (clip_region);
}
else
SelectClipRgn (hdc, NULL);
}
void
w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
int width, int height)
{
HBRUSH hb, oldhb;
HPEN hp, oldhp;
hb = CreateSolidBrush (gc->background);
hp = CreatePen (PS_SOLID, 0, gc->foreground);
oldhb = SelectObject (hdc, hb);
oldhp = SelectObject (hdc, hp);
Rectangle (hdc, x, y, x + width, y + height);
SelectObject (hdc, oldhb);
SelectObject (hdc, oldhp);
DeleteObject (hb);
DeleteObject (hp);
}
void
w32_fill_rect (f, hdc, pix, lprect)
FRAME_PTR f;
HDC hdc;
COLORREF pix;
RECT * lprect;
{
HBRUSH hb;
hb = CreateSolidBrush (pix);
FillRect (hdc, lprect, hb);
DeleteObject (hb);
}
void
w32_clear_window (f)
FRAME_PTR f;
{
RECT rect;
HDC hdc = get_frame_dc (f);
if (hdc)
{
GetClientRect (FRAME_W32_WINDOW (f), &rect);
w32_clear_rect (f, hdc, &rect);
}
release_frame_dc (f, hdc);
}
static void
x_update_begin (f)
struct frame *f;
{
struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
if (! FRAME_W32_P (f))
return;
if (display_info->regen_palette)
{
w32_regenerate_palette (f);
display_info->regen_palette = FALSE;
}
}
static void
x_update_window_begin (w)
struct window *w;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
struct w32_display_info *display_info = FRAME_W32_DISPLAY_INFO (f);
if (w32_use_visible_system_caret && w32_system_caret_hwnd)
{
SendMessage (w32_system_caret_hwnd, WM_EMACS_HIDE_CARET, 0, 0);
}
updated_window = w;
set_output_cursor (&w->cursor);
BLOCK_INPUT;
if (f == display_info->mouse_face_mouse_frame)
{
display_info->mouse_face_defer = 1;
if (FRAME_GARBAGED_P (f))
display_info->mouse_face_window = Qnil;
#if 0
if (!NILP (display_info->mouse_face_window)
&& w == XWINDOW (display_info->mouse_face_window))
{
int i;
for (i = 0; i < w->desired_matrix->nrows; ++i)
if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
break;
if (i < w->desired_matrix->nrows)
clear_mouse_face (display_info);
}
#endif
}
UNBLOCK_INPUT;
}
static void
w32_draw_vertical_window_border (w, x, y0, y1)
struct window *w;
int x, y0, y1;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
RECT r;
HDC hdc;
struct face *face;
r.left = x;
r.right = x + 1;
r.top = y0;
r.bottom = y1;
hdc = get_frame_dc (f);
face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
if (face)
w32_fill_rect (f, hdc, face->foreground, &r);
else
w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
release_frame_dc (f, hdc);
}
static void
x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
struct window *w;
int cursor_on_p, mouse_face_overwritten_p;
{
struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (XFRAME (w->frame));
if (!w->pseudo_window_p)
{
BLOCK_INPUT;
if (cursor_on_p)
display_and_set_cursor (w, 1, output_cursor.hpos,
output_cursor.vpos,
output_cursor.x, output_cursor.y);
if (draw_window_fringes (w, 1))
x_draw_vertical_border (w);
UNBLOCK_INPUT;
}
if (mouse_face_overwritten_p)
{
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
}
if (w32_use_visible_system_caret && w32_system_caret_hwnd)
{
SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
}
updated_window = NULL;
}
static void
x_update_end (f)
struct frame *f;
{
if (! FRAME_W32_P (f))
return;
FRAME_W32_DISPLAY_INFO (f)->mouse_face_defer = 0;
}
static void
w32_frame_up_to_date (f)
struct frame *f;
{
if (FRAME_W32_P (f))
{
struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
if (dpyinfo->mouse_face_deferred_gc
|| f == dpyinfo->mouse_face_mouse_frame)
{
BLOCK_INPUT;
if (dpyinfo->mouse_face_mouse_frame)
note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
dpyinfo->mouse_face_mouse_x,
dpyinfo->mouse_face_mouse_y);
dpyinfo->mouse_face_deferred_gc = 0;
UNBLOCK_INPUT;
}
}
}
static void
x_after_update_window_line (desired_row)
struct glyph_row *desired_row;
{
struct window *w = updated_window;
struct frame *f;
int width, height;
xassert (w);
if (!desired_row->mode_line_p && !w->pseudo_window_p)
desired_row->redraw_fringe_bitmaps_p = 1;
if (windows_or_buffers_changed
&& desired_row->full_width_p
&& (f = XFRAME (w->frame),
width = FRAME_INTERNAL_BORDER_WIDTH (f),
width != 0)
&& (height = desired_row->visible_height,
height > 0))
{
int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
if (WINDOWP (f->tool_bar_window)
&& w == XWINDOW (f->tool_bar_window))
y -= width;
BLOCK_INPUT;
{
HDC hdc = get_frame_dc (f);
w32_clear_area (f, hdc, 0, y, width, height);
w32_clear_area (f, hdc, FRAME_PIXEL_WIDTH (f) - width,
y, width, height);
release_frame_dc (f, hdc);
}
UNBLOCK_INPUT;
}
}
static void
w32_draw_fringe_bitmap (w, row, p)
struct window *w;
struct glyph_row *row;
struct draw_fringe_bitmap_params *p;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
HDC hdc;
struct face *face = p->face;
int rowY;
hdc = get_frame_dc (f);
rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
if (p->y < rowY)
{
int oldY = row->y;
int oldVH = row->visible_height;
row->visible_height = p->h;
row->y -= rowY - p->y;
w32_clip_to_row (w, row, -1, hdc);
row->y = oldY;
row->visible_height = oldVH;
}
else
w32_clip_to_row (w, row, -1, hdc);
if (p->bx >= 0 && !p->overlay_p)
{
w32_fill_area (f, hdc, face->background,
p->bx, p->by, p->nx, p->ny);
}
if (p->which && p->which < max_fringe_bmp)
{
HBITMAP pixmap = fringe_bmp[p->which];
HDC compat_hdc;
HANDLE horig_obj;
compat_hdc = CreateCompatibleDC (hdc);
SaveDC (hdc);
horig_obj = SelectObject (compat_hdc, pixmap);
if (p->overlay_p)
{
HBRUSH h_brush, h_orig_brush;
SetTextColor (hdc, BLACK_PIX_DEFAULT (f));
SetBkColor (hdc, WHITE_PIX_DEFAULT (f));
h_brush = CreateSolidBrush (face->foreground);
h_orig_brush = SelectObject (hdc, h_brush);
BitBlt (hdc, p->x, p->y, p->wd, p->h,
compat_hdc, 0, p->dh,
DSTINVERT);
BitBlt (hdc, p->x, p->y, p->wd, p->h,
compat_hdc, 0, p->dh,
0x2E064A);
BitBlt (hdc, p->x, p->y, p->wd, p->h,
compat_hdc, 0, p->dh,
DSTINVERT);
SelectObject (hdc, h_orig_brush);
DeleteObject (h_brush);
}
else
{
SetTextColor (hdc, face->background);
SetBkColor (hdc, (p->cursor_p
? f->output_data.w32->cursor_pixel
: face->foreground));
BitBlt (hdc, p->x, p->y, p->wd, p->h,
compat_hdc, 0, p->dh,
SRCCOPY);
}
SelectObject (compat_hdc, horig_obj);
DeleteDC (compat_hdc);
RestoreDC (hdc, -1);
}
w32_set_clip_rectangle (hdc, NULL);
release_frame_dc (f, hdc);
}
static void
w32_define_fringe_bitmap (which, bits, h, wd)
int which;
unsigned short *bits;
int h, wd;
{
if (which >= max_fringe_bmp)
{
int i = max_fringe_bmp;
max_fringe_bmp = which + 20;
fringe_bmp = (HBITMAP *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (HBITMAP));
while (i < max_fringe_bmp)
fringe_bmp[i++] = 0;
}
fringe_bmp[which] = CreateBitmap (wd, h, 1, 1, bits);
}
static void
w32_destroy_fringe_bitmap (which)
int which;
{
if (which >= max_fringe_bmp)
return;
if (fringe_bmp[which])
DeleteObject (fringe_bmp[which]);
fringe_bmp[which] = 0;
}
static void
w32_set_terminal_modes (void)
{
}
static void
w32_reset_terminal_modes (void)
{
}
XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
static int
w32_bdf_per_char_metric (font, char2b, dim, pcm)
XFontStruct *font;
wchar_t *char2b;
int dim;
XCharStruct * pcm;
{
glyph_metric * bdf_metric;
char buf[2];
if (dim == 1)
buf[0] = (char)(*char2b);
else
{
buf[0] = XCHAR2B_BYTE1 (char2b);
buf[1] = XCHAR2B_BYTE2 (char2b);
}
bdf_metric = w32_BDF_TextMetric (font->bdf, buf, dim);
if (bdf_metric)
{
pcm->width = bdf_metric->dwidth;
pcm->lbearing = bdf_metric->bbox;
pcm->rbearing = bdf_metric->dwidth
- (bdf_metric->bbox + bdf_metric->bbw);
pcm->ascent = bdf_metric->bboy + bdf_metric->bbh;
pcm->descent = -bdf_metric->bboy;
return 1;
}
return 0;
}
static int
w32_native_per_char_metric (font, char2b, font_type, pcm)
XFontStruct *font;
wchar_t *char2b;
enum w32_char_font_type font_type;
XCharStruct * pcm;
{
HDC hdc = GetDC (NULL);
HFONT old_font;
BOOL retval = FALSE;
xassert (font && char2b);
xassert (font->hfont);
xassert (font_type == UNICODE_FONT || font_type == ANSI_FONT);
old_font = SelectObject (hdc, font->hfont);
if ((font->tm.tmPitchAndFamily & TMPF_TRUETYPE) != 0)
{
ABC char_widths;
if (font_type == UNICODE_FONT)
retval = GetCharABCWidthsW (hdc, *char2b, *char2b, &char_widths);
else
retval = GetCharABCWidthsA (hdc, *char2b, *char2b, &char_widths);
if (retval)
{
#if 0
int real_width;
GetCharWidth (hdc, *char2b, *char2b, &real_width);
#endif
if (cleartype_active)
{
char_widths.abcA -= 1;
char_widths.abcC -= 1;
char_widths.abcB += 2;
}
pcm->width = char_widths.abcA + char_widths.abcB + char_widths.abcC;
#if 0
if (pcm->width != real_width)
pcm->width = (pcm->width + real_width) / 2;
#endif
pcm->lbearing = char_widths.abcA;
pcm->rbearing = char_widths.abcA + char_widths.abcB;
pcm->ascent = FONT_BASE (font);
pcm->descent = FONT_DESCENT (font);
}
}
if (!retval)
{
SIZE sz;
if (font_type == UNICODE_FONT)
retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
else
retval = GetTextExtentPoint32A (hdc, (char*)char2b, 1, &sz);
if (retval)
{
pcm->width = sz.cx - font->tm.tmOverhang;
pcm->rbearing = sz.cx;
pcm->lbearing = 0;
pcm->ascent = FONT_BASE (font);
pcm->descent = FONT_DESCENT (font);
}
}
if (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0)
{
retval = FALSE;
}
SelectObject (hdc, old_font);
ReleaseDC (NULL, hdc);
return retval;
}
XCharStruct *
w32_per_char_metric (font, char2b, font_type)
XFontStruct *font;
wchar_t *char2b;
int font_type;
{
XCharStruct *pcm;
BOOL retval;
xassert (font && char2b);
if (!font->bdf && font->per_char == NULL)
return &font->max_bounds;
else if (!font->bdf && *char2b < 128)
return &font->per_char[*char2b];
xassert (font_type != UNKNOWN_FONT);
pcm = &font->scratch;
if (font_type == BDF_1D_FONT)
retval = w32_bdf_per_char_metric (font, char2b, 1, pcm);
else if (font_type == BDF_2D_FONT)
retval = w32_bdf_per_char_metric (font, char2b, 2, pcm);
else
retval = w32_native_per_char_metric (font, char2b, font_type, pcm);
if (retval)
return pcm;
return NULL;
}
void
w32_cache_char_metrics (font)
XFontStruct *font;
{
wchar_t char2b = L'x';
if (font->bdf)
{
if (!w32_bdf_per_char_metric (font, &char2b, 1, &font->max_bounds))
{
font->max_bounds.width = FONT_MAX_WIDTH (font);
font->max_bounds.lbearing = -font->bdf->llx;
font->max_bounds.rbearing = FONT_MAX_WIDTH (font) - font->bdf->urx;
font->max_bounds.ascent = FONT_BASE (font);
font->max_bounds.descent = FONT_DESCENT (font);
}
}
else
{
if (((font->tm.tmPitchAndFamily & TMPF_FIXED_PITCH) != 0)
|| (font->tm.tmMaxCharWidth != font->tm.tmAveCharWidth))
{
int i;
font->per_char = xmalloc (128 * sizeof(XCharStruct));
for (i = 0; i < 128; i++)
{
char2b = i;
w32_native_per_char_metric (font, &char2b, ANSI_FONT,
&font->per_char[i]);
}
}
else
w32_native_per_char_metric (font, &char2b, ANSI_FONT,
&font->max_bounds);
}
}
int w32_font_is_double_byte (XFontStruct *font)
{
return font->double_byte_p;
}
static BOOL
w32_use_unicode_for_codepage (codepage)
int codepage;
{
return (w32_enable_unicode_output
&& codepage != CP_8BIT
&& (codepage == CP_UNICODE || IsValidCodePage (codepage)));
}
static int
w32_encode_char (c, char2b, font_info, two_byte_p)
int c;
wchar_t *char2b;
struct font_info *font_info;
int * two_byte_p;
{
int charset = CHAR_CHARSET (c);
int codepage;
int unicode_p = 0;
int internal_two_byte_p = 0;
XFontStruct *font = font_info->font;
internal_two_byte_p = w32_font_is_double_byte (font);
if (font_info->font_encoder)
{
struct ccl_program *ccl = font_info->font_encoder;
if (CHARSET_DIMENSION (charset) == 1)
{
ccl->reg[0] = charset;
ccl->reg[1] = XCHAR2B_BYTE2 (char2b);
ccl->reg[2] = -1;
}
else
{
ccl->reg[0] = charset;
ccl->reg[1] = XCHAR2B_BYTE1 (char2b);
ccl->reg[2] = XCHAR2B_BYTE2 (char2b);
}
ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
if (!internal_two_byte_p)
STORE_XCHAR2B (char2b, 0, ccl->reg[1]);
else
STORE_XCHAR2B (char2b, ccl->reg[1], ccl->reg[2]);
}
else if (font_info->encoding[charset])
{
int enc = font_info->encoding[charset];
if ((enc == 1 || enc == 2)
&& CHARSET_DIMENSION (charset) == 2)
STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b) | 0x80, XCHAR2B_BYTE2 (char2b));
if (enc == 1 || enc == 3
|| (enc == 4 && CHARSET_DIMENSION (charset) == 1))
STORE_XCHAR2B (char2b, XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b) | 0x80);
else if (enc == 4)
{
int sjis1, sjis2;
ENCODE_SJIS (XCHAR2B_BYTE1 (char2b), XCHAR2B_BYTE2 (char2b),
sjis1, sjis2);
STORE_XCHAR2B (char2b, sjis1, sjis2);
}
}
codepage = font_info->codepage;
if ( font && !font->bdf && w32_use_unicode_for_codepage (codepage)
&& charset != CHARSET_ASCII && charset != charset_latin_iso8859_1
&& charset != CHARSET_8_BIT_CONTROL && charset != CHARSET_8_BIT_GRAPHIC)
{
char temp[3];
temp[0] = XCHAR2B_BYTE1 (char2b);
temp[1] = XCHAR2B_BYTE2 (char2b);
temp[2] = '\0';
if (codepage != CP_UNICODE)
{
if (temp[0])
MultiByteToWideChar (codepage, 0, temp, 2, char2b, 1);
else
MultiByteToWideChar (codepage, 0, temp+1, 1, char2b, 1);
}
unicode_p = 1;
internal_two_byte_p = 1;
}
if (two_byte_p)
*two_byte_p = internal_two_byte_p;
if (!font)
return UNKNOWN_FONT;
else if (font->bdf && CHARSET_DIMENSION (charset) == 1)
return BDF_1D_FONT;
else if (font->bdf)
return BDF_2D_FONT;
else if (unicode_p)
return UNICODE_FONT;
else
return ANSI_FONT;
}
static void
w32_text_out (s, x, y,chars,nchars)
struct glyph_string * s;
int x, y;
wchar_t * chars;
int nchars;
{
int charset_dim = w32_font_is_double_byte (s->font) ? 2 : 1;
if (s->font->bdf)
w32_BDF_TextOut (s->font->bdf, s->hdc,
x, y, (char *) chars, charset_dim,
nchars * charset_dim, 0);
else if (s->first_glyph->font_type == UNICODE_FONT)
ExtTextOutW (s->hdc, x, y, 0, NULL, chars, nchars, NULL);
else
ExtTextOutA (s->hdc, x, y, 0, NULL, (char *) chars,
nchars * charset_dim, NULL);
}
static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
static void x_set_glyph_string_gc P_ ((struct glyph_string *));
static void x_draw_glyph_string_background P_ ((struct glyph_string *,
int));
static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
static void x_draw_glyph_string_box P_ ((struct glyph_string *));
static void x_draw_glyph_string P_ ((struct glyph_string *));
static void x_set_cursor_gc P_ ((struct glyph_string *));
static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
static void x_set_mouse_face_gc P_ ((struct glyph_string *));
static int w32_alloc_lighter_color (struct frame *, COLORREF *, double, int);
static void w32_setup_relief_color P_ ((struct frame *, struct relief *,
double, int, COLORREF));
static void x_setup_relief_colors P_ ((struct glyph_string *));
static void x_draw_image_glyph_string P_ ((struct glyph_string *));
static void x_draw_image_relief P_ ((struct glyph_string *));
static void x_draw_image_foreground P_ ((struct glyph_string *));
static void w32_draw_image_foreground_1 P_ ((struct glyph_string *, HBITMAP));
static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
int, int, int));
static void w32_draw_relief_rect P_ ((struct frame *, int, int, int, int,
int, int, int, int, int, int,
RECT *));
static void w32_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
int, int, int, RECT *));
#if GLYPH_DEBUG
static void x_check_font P_ ((struct frame *, XFontStruct *));
#endif
static void
x_set_cursor_gc (s)
struct glyph_string *s;
{
if (s->font == FRAME_FONT (s->f)
&& s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
&& s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
&& !s->cmp)
s->gc = s->f->output_data.w32->cursor_gc;
else
{
XGCValues xgcv;
unsigned long mask;
xgcv.background = s->f->output_data.w32->cursor_pixel;
xgcv.foreground = s->face->background;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = s->face->foreground;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = s->f->output_data.w32->cursor_foreground_pixel;
if (xgcv.foreground == xgcv.background)
xgcv.foreground = s->face->foreground;
if (xgcv.background == s->face->background
&& xgcv.foreground == s->face->foreground)
{
xgcv.background = s->face->foreground;
xgcv.foreground = s->face->background;
}
IF_DEBUG (x_check_font (s->f, s->font));
xgcv.font = s->font;
mask = GCForeground | GCBackground | GCFont;
if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
mask, &xgcv);
else
FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
= XCreateGC (NULL, s->window, mask, &xgcv);
s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
}
}
static void
x_set_mouse_face_gc (s)
struct glyph_string *s;
{
int face_id;
struct face *face;
face_id = FRAME_W32_DISPLAY_INFO (s->f)->mouse_face_face_id;
face = FACE_FROM_ID (s->f, face_id);
if (face == NULL)
face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
if (s->first_glyph->type == CHAR_GLYPH)
face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
else
face_id = FACE_FOR_CHAR (s->f, face, 0);
s->face = FACE_FROM_ID (s->f, face_id);
PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
if (s->font == s->face->font)
s->gc = s->face->gc;
else
{
XGCValues xgcv;
unsigned long mask;
xgcv.background = s->face->background;
xgcv.foreground = s->face->foreground;
IF_DEBUG (x_check_font (s->f, s->font));
xgcv.font = s->font;
mask = GCForeground | GCBackground | GCFont;
if (FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc)
XChangeGC (NULL, FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc,
mask, &xgcv);
else
FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc
= XCreateGC (NULL, s->window, mask, &xgcv);
s->gc = FRAME_W32_DISPLAY_INFO (s->f)->scratch_cursor_gc;
}
xassert (s->gc != 0);
}
static INLINE void
x_set_mode_line_face_gc (s)
struct glyph_string *s;
{
s->gc = s->face->gc;
}
static INLINE void
x_set_glyph_string_gc (s)
struct glyph_string *s;
{
PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
if (s->hl == DRAW_NORMAL_TEXT)
{
s->gc = s->face->gc;
s->stippled_p = s->face->stipple != 0;
}
else if (s->hl == DRAW_INVERSE_VIDEO)
{
x_set_mode_line_face_gc (s);
s->stippled_p = s->face->stipple != 0;
}
else if (s->hl == DRAW_CURSOR)
{
x_set_cursor_gc (s);
s->stippled_p = 0;
}
else if (s->hl == DRAW_MOUSE_FACE)
{
x_set_mouse_face_gc (s);
s->stippled_p = s->face->stipple != 0;
}
else if (s->hl == DRAW_IMAGE_RAISED
|| s->hl == DRAW_IMAGE_SUNKEN)
{
s->gc = s->face->gc;
s->stippled_p = s->face->stipple != 0;
}
else
{
s->gc = s->face->gc;
s->stippled_p = s->face->stipple != 0;
}
xassert (s->gc != 0);
}
static INLINE void
x_set_glyph_string_clipping (s)
struct glyph_string *s;
{
RECT r;
get_glyph_string_clip_rect (s, &r);
w32_set_clip_rectangle (s->hdc, &r);
}
static void
w32_compute_glyph_string_overhangs (s)
struct glyph_string *s;
{
}
static void
w32_get_glyph_overhangs (glyph, f, left, right)
struct glyph *glyph;
struct frame *f;
int *left, *right;
{
HDC hdc = get_frame_dc (f);
x_get_glyph_overhangs (glyph, f, left, right);
release_frame_dc (f, hdc);
}
static INLINE void
x_clear_glyph_string_rect (s, x, y, w, h)
struct glyph_string *s;
int x, y, w, h;
{
int real_x = x;
int real_y = y;
int real_w = w;
int real_h = h;
#if 0
if (s->gc->clip_mask == Rect)
{
real_x = max (real_x, s->gc->clip_rectangle.left);
real_y = max (real_y, s->gc->clip_rectangle.top);
real_w = min (real_w, s->gc->clip_rectangle.right
- s->gc->clip_rectangle.left);
real_h = min (real_h, s->gc->clip_rectangle.bottom
- s->gc->clip_rectangle.top);
}
#endif
w32_fill_area (s->f, s->hdc, s->gc->background, real_x, real_y,
real_w, real_h);
}
static void
x_draw_glyph_string_background (s, force_p)
struct glyph_string *s;
int force_p;
{
if (!s->background_filled_p)
{
int box_line_width = max (s->face->box_line_width, 0);
#if 0
if (s->stippled_p)
{
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
XFillRectangle (s->display, s->window, s->gc, s->x,
s->y + box_line_width,
s->background_width,
s->height - 2 * box_line_width);
XSetFillStyle (s->display, s->gc, FillSolid);
s->background_filled_p = 1;
}
else
#endif
if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
|| s->font_not_found_p
|| s->extends_to_end_of_line_p
|| s->font->bdf
|| force_p)
{
x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
s->background_width,
s->height - 2 * box_line_width);
s->background_filled_p = 1;
}
}
}
static void
x_draw_glyph_string_foreground (s)
struct glyph_string *s;
{
int i, x;
HFONT old_font;
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + abs (s->face->box_line_width);
else
x = s->x;
if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
SetBkMode (s->hdc, TRANSPARENT);
else
SetBkMode (s->hdc, OPAQUE);
SetTextColor (s->hdc, s->gc->foreground);
SetBkColor (s->hdc, s->gc->background);
SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
if (s->font && s->font->hfont)
old_font = SelectObject (s->hdc, s->font->hfont);
if (s->font_not_found_p)
{
for (i = 0; i < s->nchars; ++i)
{
struct glyph *g = s->first_glyph + i;
w32_draw_rectangle (s->hdc, s->gc, x, s->y, g->pixel_width - 1,
s->height - 1);
x += g->pixel_width;
}
}
else
{
char *char1b = (char *) s->char2b;
int boff = s->font_info->baseline_offset;
if (s->font_info->vertical_centering)
boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
if (!s->two_byte_p)
for (i = 0; i < s->nchars; ++i)
char1b[i] = XCHAR2B_BYTE2 (&s->char2b[i]);
w32_text_out (s, x, s->ybase - boff, s->char2b, s->nchars);
if (s->face->overstrike)
{
int old_BkMode = SetBkMode (s->hdc, TRANSPARENT);
w32_text_out (s, x + 1, s->ybase - boff, s->char2b, s->nchars);
if (old_BkMode && old_BkMode != TRANSPARENT)
SetBkMode (s->hdc, old_BkMode);
}
}
if (s->font && s->font->hfont)
SelectObject (s->hdc, old_font);
}
static void
x_draw_composite_glyph_string_foreground (s)
struct glyph_string *s;
{
int i, x;
HFONT old_font;
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p)
x = s->x + abs (s->face->box_line_width);
else
x = s->x;
SetTextColor (s->hdc, s->gc->foreground);
SetBkColor (s->hdc, s->gc->background);
SetBkMode (s->hdc, TRANSPARENT);
SetTextAlign (s->hdc, TA_BASELINE | TA_LEFT);
if (s->font && s->font->hfont)
old_font = SelectObject (s->hdc, s->font->hfont);
if (s->font_not_found_p)
{
if (s->gidx == 0)
w32_draw_rectangle (s->hdc, s->gc, x, s->y, s->width - 1,
s->height - 1);
}
else
{
for (i = 0; i < s->nchars; i++, ++s->gidx)
{
w32_text_out (s, x + s->cmp->offsets[s->gidx * 2],
s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
s->char2b + i, 1);
if (s->face->overstrike)
w32_text_out (s, x + s->cmp->offsets[s->gidx * 2] + 1,
s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
s->char2b + i, 1);
}
}
if (s->font && s->font->hfont)
SelectObject (s->hdc, old_font);
}
#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
static int
w32_alloc_lighter_color (f, color, factor, delta)
struct frame *f;
COLORREF *color;
double factor;
int delta;
{
COLORREF new;
long bright;
delta /= 256;
xassert (factor >= 0);
new = PALETTERGB (min (0xff, factor * GetRValue (*color)),
min (0xff, factor * GetGValue (*color)),
min (0xff, factor * GetBValue (*color)));
bright = (2 * GetRValue (*color) + 3 * GetGValue (*color)
+ GetBValue (*color)) / 6;
if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
{
double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
int min_delta = delta * dimness * factor / 2;
if (factor < 1)
new = PALETTERGB (max (0, min (0xff, min_delta - GetRValue (*color))),
max (0, min (0xff, min_delta - GetGValue (*color))),
max (0, min (0xff, min_delta - GetBValue (*color))));
else
new = PALETTERGB (max (0, min (0xff, min_delta + GetRValue (*color))),
max (0, min (0xff, min_delta + GetGValue (*color))),
max (0, min (0xff, min_delta + GetBValue (*color))));
}
if (new == *color)
new = PALETTERGB (max (0, min (0xff, delta + GetRValue (*color))),
max (0, min (0xff, delta + GetGValue (*color))),
max (0, min (0xff, delta + GetBValue (*color))));
if (new == *color)
return 0;
*color = new;
return 1;
}
static void
w32_setup_relief_color (f, relief, factor, delta, default_pixel)
struct frame *f;
struct relief *relief;
double factor;
int delta;
COLORREF default_pixel;
{
XGCValues xgcv;
struct w32_output *di = f->output_data.w32;
unsigned long mask = GCForeground;
COLORREF pixel;
COLORREF background = di->relief_background;
struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
xgcv.foreground = default_pixel;
pixel = background;
if (w32_alloc_lighter_color (f, &pixel, factor, delta))
{
relief->allocated_p = 1;
xgcv.foreground = relief->pixel = pixel;
}
if (relief->gc == 0)
{
#if 0
xgcv.stipple = dpyinfo->gray;
mask |= GCStipple;
#endif
relief->gc = XCreateGC (NULL, FRAME_W32_WINDOW (f), mask, &xgcv);
}
else
XChangeGC (NULL, relief->gc, mask, &xgcv);
}
static void
x_setup_relief_colors (s)
struct glyph_string *s;
{
struct w32_output *di = s->f->output_data.w32;
COLORREF color;
if (s->face->use_box_color_for_shadows_p)
color = s->face->box_color;
else if (s->first_glyph->type == IMAGE_GLYPH
&& s->img->pixmap
&& !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
color = IMAGE_BACKGROUND (s->img, s->f, 0);
else
color = s->gc->background;
if (di->white_relief.gc == 0
|| color != di->relief_background)
{
di->relief_background = color;
w32_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
WHITE_PIX_DEFAULT (s->f));
w32_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
BLACK_PIX_DEFAULT (s->f));
}
}
static void
w32_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
raised_p, top_p, bot_p, left_p, right_p, clip_rect)
struct frame *f;
int left_x, top_y, right_x, bottom_y, width;
int top_p, bot_p, left_p, right_p, raised_p;
RECT *clip_rect;
{
int i;
XGCValues gc;
HDC hdc = get_frame_dc (f);
if (raised_p)
gc.foreground = f->output_data.w32->white_relief.gc->foreground;
else
gc.foreground = f->output_data.w32->black_relief.gc->foreground;
w32_set_clip_rectangle (hdc, clip_rect);
if (top_p)
for (i = 0; i < width; ++i)
w32_fill_area (f, hdc, gc.foreground,
left_x + i * left_p, top_y + i,
right_x - left_x - i * (left_p + right_p ) + 1, 1);
if (left_p)
for (i = 0; i < width; ++i)
w32_fill_area (f, hdc, gc.foreground,
left_x + i, top_y + i, 1,
bottom_y - top_y - 2 * i + 1);
if (raised_p)
gc.foreground = f->output_data.w32->black_relief.gc->foreground;
else
gc.foreground = f->output_data.w32->white_relief.gc->foreground;
if (bot_p)
for (i = 0; i < width; ++i)
w32_fill_area (f, hdc, gc.foreground,
left_x + i * left_p, bottom_y - i,
right_x - left_x - i * (left_p + right_p) + 1, 1);
if (right_p)
for (i = 0; i < width; ++i)
w32_fill_area (f, hdc, gc.foreground,
right_x - i, top_y + i + 1, 1,
bottom_y - top_y - 2 * i - 1);
w32_set_clip_rectangle (hdc, NULL);
release_frame_dc (f, hdc);
}
static void
w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
left_p, right_p, clip_rect)
struct glyph_string *s;
int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
RECT *clip_rect;
{
w32_set_clip_rectangle (s->hdc, clip_rect);
w32_fill_area (s->f, s->hdc, s->face->box_color,
left_x, top_y, right_x - left_x + 1, width);
if (left_p)
{
w32_fill_area (s->f, s->hdc, s->face->box_color,
left_x, top_y, width, bottom_y - top_y + 1);
}
w32_fill_area (s->f, s->hdc, s->face->box_color,
left_x, bottom_y - width + 1, right_x - left_x + 1, width);
if (right_p)
{
w32_fill_area (s->f, s->hdc, s->face->box_color,
right_x - width + 1, top_y, width, bottom_y - top_y + 1);
}
w32_set_clip_rectangle (s->hdc, NULL);
}
static void
x_draw_glyph_string_box (s)
struct glyph_string *s;
{
int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
int left_p, right_p;
struct glyph *last_glyph;
RECT clip_rect;
last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
? WINDOW_RIGHT_EDGE_X (s->w)
: window_box_right (s->w, s->area));
last_glyph = (s->cmp || s->img
? s->first_glyph
: s->first_glyph + s->nchars - 1);
width = abs (s->face->box_line_width);
raised_p = s->face->box == FACE_RAISED_BOX;
left_x = s->x;
right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
? last_x - 1
: min (last_x, s->x + s->background_width) - 1));
top_y = s->y;
bottom_y = top_y + s->height - 1;
left_p = (s->first_glyph->left_box_line_p
|| (s->hl == DRAW_MOUSE_FACE
&& (s->prev == NULL
|| s->prev->hl != s->hl)));
right_p = (last_glyph->right_box_line_p
|| (s->hl == DRAW_MOUSE_FACE
&& (s->next == NULL
|| s->next->hl != s->hl)));
get_glyph_string_clip_rect (s, &clip_rect);
if (s->face->box == FACE_SIMPLE_BOX)
w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
left_p, right_p, &clip_rect);
else
{
x_setup_relief_colors (s);
w32_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
width, raised_p, 1, 1, left_p, right_p, &clip_rect);
}
}
static void
x_draw_image_foreground (s)
struct glyph_string *s;
{
int x = s->x;
int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += abs (s->face->box_line_width);
if (s->slice.x == 0)
x += s->img->hmargin;
if (s->slice.y == 0)
y += s->img->vmargin;
SaveDC (s->hdc);
if (s->img->pixmap)
{
HDC compat_hdc = CreateCompatibleDC (s->hdc);
HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
SetBkColor (compat_hdc, RGB (255, 255, 255));
SetTextColor (s->hdc, RGB (0, 0, 0));
x_set_glyph_string_clipping (s);
if (s->img->mask)
{
HDC mask_dc = CreateCompatibleDC (s->hdc);
HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
SetTextColor (s->hdc, RGB (255, 255, 255));
SetBkColor (s->hdc, RGB (0, 0, 0));
BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
mask_dc, s->slice.x, s->slice.y, SRCAND);
BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
SelectObject (mask_dc, mask_orig_obj);
DeleteDC (mask_dc);
}
else
{
SetTextColor (s->hdc, s->gc->foreground);
SetBkColor (s->hdc, s->gc->background);
BitBlt (s->hdc, x, y, s->slice.width, s->slice.height,
compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
if (s->hl == DRAW_CURSOR)
{
int r = s->img->relief;
if (r < 0) r = -r;
w32_draw_rectangle (s->hdc, s->gc, x - r, y - r ,
s->slice.width + r*2 - 1,
s->slice.height + r*2 - 1);
}
}
w32_set_clip_rectangle (s->hdc, NULL);
SelectObject (s->hdc, orig_brush);
DeleteObject (fg_brush);
SelectObject (compat_hdc, orig_obj);
DeleteDC (compat_hdc);
}
else
w32_draw_rectangle (s->hdc, s->gc, x, y,
s->slice.width - 1, s->slice.height - 1);
RestoreDC (s->hdc ,-1);
}
static void
x_draw_image_relief (s)
struct glyph_string *s;
{
int x0, y0, x1, y1, thick, raised_p;
RECT r;
int x = s->x;
int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += abs (s->face->box_line_width);
if (s->slice.x == 0)
x += s->img->hmargin;
if (s->slice.y == 0)
y += s->img->vmargin;
if (s->hl == DRAW_IMAGE_SUNKEN
|| s->hl == DRAW_IMAGE_RAISED)
{
thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
raised_p = s->hl == DRAW_IMAGE_RAISED;
}
else
{
thick = abs (s->img->relief);
raised_p = s->img->relief > 0;
}
x0 = x - thick;
y0 = y - thick;
x1 = x + s->slice.width + thick - 1;
y1 = y + s->slice.height + thick - 1;
x_setup_relief_colors (s);
get_glyph_string_clip_rect (s, &r);
w32_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
s->slice.y == 0,
s->slice.y + s->slice.height == s->img->height,
s->slice.x == 0,
s->slice.x + s->slice.width == s->img->width,
&r);
}
static void
w32_draw_image_foreground_1 (s, pixmap)
struct glyph_string *s;
HBITMAP pixmap;
{
HDC hdc = CreateCompatibleDC (s->hdc);
HGDIOBJ orig_hdc_obj = SelectObject (hdc, pixmap);
int x = 0;
int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
if (s->face->box != FACE_NO_BOX
&& s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += abs (s->face->box_line_width);
if (s->slice.x == 0)
x += s->img->hmargin;
if (s->slice.y == 0)
y += s->img->vmargin;
if (s->img->pixmap)
{
HDC compat_hdc = CreateCompatibleDC (hdc);
HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
HBRUSH orig_brush = SelectObject (hdc, fg_brush);
HGDIOBJ orig_obj = SelectObject (compat_hdc, s->img->pixmap);
if (s->img->mask)
{
HDC mask_dc = CreateCompatibleDC (hdc);
HGDIOBJ mask_orig_obj = SelectObject (mask_dc, s->img->mask);
SetTextColor (hdc, RGB (0, 0, 0));
SetBkColor (hdc, RGB (255, 255, 255));
BitBlt (hdc, x, y, s->slice.width, s->slice.height,
compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
BitBlt (hdc, x, y, s->slice.width, s->slice.height,
mask_dc, s->slice.x, s->slice.y, SRCAND);
BitBlt (hdc, x, y, s->slice.width, s->slice.height,
compat_hdc, s->slice.x, s->slice.y, SRCINVERT);
SelectObject (mask_dc, mask_orig_obj);
DeleteDC (mask_dc);
}
else
{
SetTextColor (hdc, s->gc->foreground);
SetBkColor (hdc, s->gc->background);
BitBlt (hdc, x, y, s->slice.width, s->slice.height,
compat_hdc, s->slice.x, s->slice.y, SRCCOPY);
if (s->hl == DRAW_CURSOR)
{
int r = s->img->relief;
if (r < 0) r = -r;
w32_draw_rectangle (hdc, s->gc, x - r, y - r,
s->slice.width + r*2 - 1,
s->slice.height + r*2 - 1);
}
}
SelectObject (hdc, orig_brush);
DeleteObject (fg_brush);
SelectObject (compat_hdc, orig_obj);
DeleteDC (compat_hdc);
}
else
w32_draw_rectangle (hdc, s->gc, x, y,
s->slice.width - 1, s->slice.height - 1);
SelectObject (hdc, orig_hdc_obj);
DeleteDC (hdc);
}
static void
x_draw_glyph_string_bg_rect (s, x, y, w, h)
struct glyph_string *s;
int x, y, w, h;
{
#if 0
if (s->stippled_p)
{
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
XSetFillStyle (s->display, s->gc, FillSolid);
}
else
#endif
x_clear_glyph_string_rect (s, x, y, w, h);
}
static void
x_draw_image_glyph_string (s)
struct glyph_string *s;
{
int x, y;
int box_line_hwidth = abs (s->face->box_line_width);
int box_line_vwidth = max (s->face->box_line_width, 0);
int height;
HBITMAP pixmap = 0;
height = s->height - 2 * box_line_vwidth;
s->stippled_p = s->face->stipple != 0;
if (height > s->slice.height
|| s->img->hmargin
|| s->img->vmargin
|| s->img->mask
|| s->img->pixmap == 0
|| s->width != s->background_width)
{
x = s->x;
if (s->first_glyph->left_box_line_p
&& s->slice.x == 0)
x += box_line_hwidth;
y = s->y;
if (s->slice.y == 0)
y += box_line_vwidth;
#if 0
if (s->img->mask)
{
Screen *screen = FRAME_X_SCREEN (s->f);
int depth = DefaultDepthOfScreen (screen);
pixmap = XCreatePixmap (s->display, s->window,
s->background_width,
s->height, depth);
XSetClipMask (s->display, s->gc, None);
if (s->stippled_p)
{
XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
XFillRectangle (s->display, pixmap, s->gc,
0, 0, s->background_width, s->height);
XSetFillStyle (s->display, s->gc, FillSolid);
}
else
{
XGCValues xgcv;
XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
&xgcv);
XSetForeground (s->display, s->gc, xgcv.background);
XFillRectangle (s->display, pixmap, s->gc,
0, 0, s->background_width, s->height);
XSetForeground (s->display, s->gc, xgcv.foreground);
}
}
else
#endif
x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
s->background_filled_p = 1;
}
if (pixmap != 0)
{
w32_draw_image_foreground_1 (s, pixmap);
x_set_glyph_string_clipping (s);
{
HDC compat_hdc = CreateCompatibleDC (s->hdc);
HBRUSH fg_brush = CreateSolidBrush (s->gc->foreground);
HBRUSH orig_brush = SelectObject (s->hdc, fg_brush);
HGDIOBJ orig_obj = SelectObject (compat_hdc, pixmap);
SetTextColor (s->hdc, s->gc->foreground);
SetBkColor (s->hdc, s->gc->background);
BitBlt (s->hdc, s->x, s->y, s->background_width, s->height,
compat_hdc, 0, 0, SRCCOPY);
SelectObject (s->hdc, orig_brush);
DeleteObject (fg_brush);
SelectObject (compat_hdc, orig_obj);
DeleteDC (compat_hdc);
}
DeleteObject (pixmap);
pixmap = 0;
}
else
x_draw_image_foreground (s);
if (s->img->relief
|| s->hl == DRAW_IMAGE_RAISED
|| s->hl == DRAW_IMAGE_SUNKEN)
x_draw_image_relief (s);
}
static void
x_draw_stretch_glyph_string (s)
struct glyph_string *s;
{
xassert (s->first_glyph->type == STRETCH_GLYPH);
s->stippled_p = s->face->stipple != 0;
if (s->hl == DRAW_CURSOR
&& !x_stretch_cursor_p)
{
int width, background_width = s->background_width;
int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
if (x < left_x)
{
background_width -= left_x - x;
x = left_x;
}
width = min (FRAME_COLUMN_WIDTH (s->f), background_width);
x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
if (width < background_width)
{
XGCValues *gc = s->face->gc;
int y = s->y;
int w = background_width - width, h = s->height;
RECT r;
HDC hdc = s->hdc;
x += width;
if (s->row->mouse_face_p
&& cursor_in_mouse_face_p (s->w))
{
x_set_mouse_face_gc (s);
gc = s->gc;
}
else
gc = s->face->gc;
get_glyph_string_clip_rect (s, &r);
w32_set_clip_rectangle (hdc, &r);
#if 0
if (s->face->stipple)
{
XSetFillStyle (s->display, gc, FillOpaqueStippled);
XFillRectangle (s->display, s->window, gc, x, y, w, h);
XSetFillStyle (s->display, gc, FillSolid);
}
else
#endif
{
w32_fill_area (s->f, s->hdc, gc->background, x, y, w, h);
}
}
}
else if (!s->background_filled_p)
{
int background_width = s->background_width;
int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
if (x < left_x && !s->row->mode_line_p)
{
background_width -= left_x - x;
x = left_x;
}
if (background_width > 0)
x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height);
}
s->background_filled_p = 1;
}
static void
x_draw_glyph_string (s)
struct glyph_string *s;
{
int relief_drawn_p = 0;
if (s->next && s->right_overhang && !s->for_overlaps)
{
xassert (s->next->img == NULL);
x_set_glyph_string_gc (s->next);
x_set_glyph_string_clipping (s->next);
x_draw_glyph_string_background (s->next, 1);
}
x_set_glyph_string_gc (s);
if (!s->for_overlaps
&& s->face->box != FACE_NO_BOX
&& (s->first_glyph->type == CHAR_GLYPH
|| s->first_glyph->type == COMPOSITE_GLYPH))
{
x_set_glyph_string_clipping (s);
x_draw_glyph_string_background (s, 1);
x_draw_glyph_string_box (s);
x_set_glyph_string_clipping (s);
relief_drawn_p = 1;
}
else
x_set_glyph_string_clipping (s);
switch (s->first_glyph->type)
{
case IMAGE_GLYPH:
x_draw_image_glyph_string (s);
break;
case STRETCH_GLYPH:
x_draw_stretch_glyph_string (s);
break;
case CHAR_GLYPH:
if (s->for_overlaps)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 0);
x_draw_glyph_string_foreground (s);
break;
case COMPOSITE_GLYPH:
if (s->for_overlaps || s->gidx > 0)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 1);
x_draw_composite_glyph_string_foreground (s);
break;
default:
abort ();
}
if (!s->for_overlaps)
{
if (s->face->underline_p
&& (s->font->bdf || !s->font->tm.tmUnderlined))
{
unsigned long h = 1;
unsigned long dy = 0;
if (x_underline_at_descent_line)
dy = s->height - h;
else
{
dy = s->height - h;
}
if (s->face->underline_defaulted_p)
{
w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
s->y + dy, s->background_width, 1);
}
else
{
w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
s->y + dy, s->background_width, 1);
}
}
if (s->face->overline_p)
{
unsigned long dy = 0, h = 1;
if (s->face->overline_color_defaulted_p)
{
w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
s->y + dy, s->background_width, h);
}
else
{
w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
s->y + dy, s->background_width, h);
}
}
if (s->face->strike_through_p
&& (s->font->bdf || !s->font->tm.tmStruckOut))
{
unsigned long h = 1;
unsigned long dy = (s->height - h) / 2;
if (s->face->strike_through_color_defaulted_p)
{
w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, s->y + dy,
s->width, h);
}
else
{
w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
s->y + dy, s->width, h);
}
}
if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
x_draw_glyph_string_box (s);
}
w32_set_clip_rectangle (s->hdc, NULL);
}
void
w32_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
struct frame *f;
int x, y, width, height, shift_by;
{
HDC hdc;
hdc = get_frame_dc (f);
BitBlt (hdc, x + shift_by, y, width, height,
hdc, x, y, SRCCOPY);
release_frame_dc (f, hdc);
}
static void
x_delete_glyphs (n)
register int n;
{
struct frame *f;
if (updating_frame)
f = updating_frame;
else
f = SELECTED_FRAME ();
if (! FRAME_W32_P (f))
return;
abort ();
}
static void
x_clear_frame ()
{
struct frame *f;
if (updating_frame)
f = updating_frame;
else
f = SELECTED_FRAME ();
if (! FRAME_W32_P (f))
return;
mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
output_cursor.hpos = output_cursor.vpos = 0;
output_cursor.x = -1;
BLOCK_INPUT;
w32_clear_window (f);
x_scroll_bar_clear (f);
UNBLOCK_INPUT;
}
static void
w32_ring_bell (void)
{
struct frame *f;
f = SELECTED_FRAME ();
BLOCK_INPUT;
if (FRAME_W32_P (f) && visible_bell)
{
int i;
HWND hwnd = FRAME_W32_WINDOW (SELECTED_FRAME ());
for (i = 0; i < 5; i++)
{
FlashWindow (hwnd, TRUE);
Sleep (10);
}
FlashWindow (hwnd, FALSE);
}
else
w32_sys_ring_bell ();
UNBLOCK_INPUT;
}
static void
w32_set_terminal_window (n)
register int n;
{
}
static void
x_ins_del_lines (vpos, n)
int vpos, n;
{
struct frame *f;
if (updating_frame)
f = updating_frame;
else
f = SELECTED_FRAME ();
if (! FRAME_W32_P (f))
return;
abort ();
}
static void
x_scroll_run (w, run)
struct window *w;
struct run *run;
{
struct frame *f = XFRAME (w->frame);
int x, y, width, height, from_y, to_y, bottom_y;
HWND hwnd = FRAME_W32_WINDOW (f);
HRGN expect_dirty;
window_box (w, -1, &x, &y, &width, &height);
from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
bottom_y = y + height;
if (to_y < from_y)
{
if (from_y + run->height > bottom_y)
height = bottom_y - from_y;
else
height = run->height;
expect_dirty = CreateRectRgn (x, y + height, x + width, bottom_y);
}
else
{
if (to_y + run->height > bottom_y)
height = bottom_y - to_y;
else
height = run->height;
expect_dirty = CreateRectRgn (x, y, x + width, to_y);
}
BLOCK_INPUT;
updated_window = w;
x_clear_cursor (w);
{
RECT from;
RECT to;
HRGN dirty = CreateRectRgn (0, 0, 0, 0);
HRGN combined = CreateRectRgn (0, 0, 0, 0);
from.left = to.left = x;
from.right = to.right = x + width;
from.top = from_y;
from.bottom = from_y + height;
to.top = y;
to.bottom = bottom_y;
ScrollWindowEx (hwnd, 0, to_y - from_y, &from, &to, dirty,
NULL, SW_INVALIDATE);
CombineRgn (combined, dirty, expect_dirty, RGN_OR);
if (!EqualRgn (combined, expect_dirty))
SET_FRAME_GARBAGED (f);
DeleteObject (dirty);
DeleteObject (combined);
}
UNBLOCK_INPUT;
DeleteObject (expect_dirty);
}
static void
frame_highlight (f)
struct frame *f;
{
x_update_cursor (f, 1);
}
static void
frame_unhighlight (f)
struct frame *f;
{
x_update_cursor (f, 1);
}
static void
x_new_focus_frame (dpyinfo, frame)
struct w32_display_info *dpyinfo;
struct frame *frame;
{
struct frame *old_focus = dpyinfo->w32_focus_frame;
if (frame != dpyinfo->w32_focus_frame)
{
dpyinfo->w32_focus_frame = frame;
if (old_focus && old_focus->auto_lower)
x_lower_frame (old_focus);
if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
pending_autoraise_frame = dpyinfo->w32_focus_frame;
else
pending_autoraise_frame = 0;
}
x_frame_rehighlight (dpyinfo);
}
static void
x_focus_changed (type, state, dpyinfo, frame, bufp)
int type;
int state;
struct w32_display_info *dpyinfo;
struct frame *frame;
struct input_event *bufp;
{
if (type == WM_SETFOCUS)
{
if (dpyinfo->w32_focus_event_frame != frame)
{
x_new_focus_frame (dpyinfo, frame);
dpyinfo->w32_focus_event_frame = frame;
if (GC_NILP (Vterminal_frame)
&& GC_CONSP (Vframe_list)
&& !GC_NILP (XCDR (Vframe_list)))
{
bufp->kind = FOCUS_IN_EVENT;
XSETFRAME (bufp->frame_or_window, frame);
}
}
frame->output_data.x->focus_state |= state;
}
else if (type == WM_KILLFOCUS)
{
frame->output_data.x->focus_state &= ~state;
if (dpyinfo->w32_focus_event_frame == frame)
{
dpyinfo->w32_focus_event_frame = 0;
x_new_focus_frame (dpyinfo, 0);
}
}
}
static void
w32_detect_focus_change (dpyinfo, event, bufp)
struct w32_display_info *dpyinfo;
W32Msg *event;
struct input_event *bufp;
{
struct frame *frame;
frame = x_any_window_to_frame (dpyinfo, event->msg.hwnd);
if (! frame)
return;
x_focus_changed (event->msg.message,
(event->msg.message == WM_KILLFOCUS ?
FOCUS_IMPLICIT : FOCUS_EXPLICIT),
dpyinfo, frame, bufp);
}
void
x_mouse_leave (dpyinfo)
struct w32_display_info *dpyinfo;
{
x_new_focus_frame (dpyinfo, dpyinfo->w32_focus_event_frame);
}
static void
w32_frame_rehighlight (frame)
struct frame *frame;
{
if (! FRAME_W32_P (frame))
return;
x_frame_rehighlight (FRAME_W32_DISPLAY_INFO (frame));
}
static void
x_frame_rehighlight (dpyinfo)
struct w32_display_info *dpyinfo;
{
struct frame *old_highlight = dpyinfo->x_highlight_frame;
if (dpyinfo->w32_focus_frame)
{
dpyinfo->x_highlight_frame
= ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame)))
? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame))
: dpyinfo->w32_focus_frame);
if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
{
FRAME_FOCUS_FRAME (dpyinfo->w32_focus_frame) = Qnil;
dpyinfo->x_highlight_frame = dpyinfo->w32_focus_frame;
}
}
else
dpyinfo->x_highlight_frame = 0;
if (dpyinfo->x_highlight_frame != old_highlight)
{
if (old_highlight)
frame_unhighlight (old_highlight);
if (dpyinfo->x_highlight_frame)
frame_highlight (dpyinfo->x_highlight_frame);
}
}
char *
x_get_keysym_name (keysym)
int keysym;
{
static char value[100];
BLOCK_INPUT;
GetKeyNameText (keysym, value, 100);
UNBLOCK_INPUT;
return value;
}
BOOL
parse_button (message, xbutton, pbutton, pup)
int message;
int xbutton;
int * pbutton;
int * pup;
{
int button = 0;
int up = 0;
switch (message)
{
case WM_LBUTTONDOWN:
button = 0;
up = 0;
break;
case WM_LBUTTONUP:
button = 0;
up = 1;
break;
case WM_MBUTTONDOWN:
if (NILP (Vw32_swap_mouse_buttons))
button = 1;
else
button = 2;
up = 0;
break;
case WM_MBUTTONUP:
if (NILP (Vw32_swap_mouse_buttons))
button = 1;
else
button = 2;
up = 1;
break;
case WM_RBUTTONDOWN:
if (NILP (Vw32_swap_mouse_buttons))
button = 2;
else
button = 1;
up = 0;
break;
case WM_RBUTTONUP:
if (NILP (Vw32_swap_mouse_buttons))
button = 2;
else
button = 1;
up = 1;
break;
case WM_XBUTTONDOWN:
button = xbutton + 2;
up = 0;
break;
case WM_XBUTTONUP:
button = xbutton + 2;
up = 1;
break;
default:
return (FALSE);
}
if (pup) *pup = up;
if (pbutton) *pbutton = button;
return (TRUE);
}
static Lisp_Object
construct_mouse_click (result, msg, f)
struct input_event *result;
W32Msg *msg;
struct frame *f;
{
int button;
int up;
parse_button (msg->msg.message, HIWORD (msg->msg.wParam),
&button, &up);
result->kind = MOUSE_CLICK_EVENT;
result->code = button;
result->timestamp = msg->msg.time;
result->modifiers = (msg->dwModifiers
| (up
? up_modifier
: down_modifier));
XSETINT (result->x, LOWORD (msg->msg.lParam));
XSETINT (result->y, HIWORD (msg->msg.lParam));
XSETFRAME (result->frame_or_window, f);
result->arg = Qnil;
return Qnil;
}
static Lisp_Object
construct_mouse_wheel (result, msg, f)
struct input_event *result;
W32Msg *msg;
struct frame *f;
{
POINT p;
int delta;
result->kind = WHEEL_EVENT;
result->code = 0;
result->timestamp = msg->msg.time;
delta = GET_WHEEL_DELTA_WPARAM (msg->msg.wParam);
result->modifiers = (msg->dwModifiers
| ((delta < 0 ) ? down_modifier : up_modifier));
p.x = (short) LOWORD (msg->msg.lParam);
p.y = (short) HIWORD (msg->msg.lParam);
ScreenToClient (msg->msg.hwnd, &p);
XSETINT (result->x, p.x);
XSETINT (result->y, p.y);
XSETFRAME (result->frame_or_window, f);
result->arg = Qnil;
return Qnil;
}
static Lisp_Object
construct_drag_n_drop (result, msg, f)
struct input_event *result;
W32Msg *msg;
struct frame *f;
{
Lisp_Object files;
Lisp_Object frame;
HDROP hdrop;
POINT p;
WORD num_files;
char *name;
int i, len;
result->kind = DRAG_N_DROP_EVENT;
result->code = 0;
result->timestamp = msg->msg.time;
result->modifiers = msg->dwModifiers;
hdrop = (HDROP) msg->msg.wParam;
DragQueryPoint (hdrop, &p);
#if 0
p.x = LOWORD (msg->msg.lParam);
p.y = HIWORD (msg->msg.lParam);
ScreenToClient (msg->msg.hwnd, &p);
#endif
XSETINT (result->x, p.x);
XSETINT (result->y, p.y);
num_files = DragQueryFile (hdrop, 0xFFFFFFFF, NULL, 0);
files = Qnil;
for (i = 0; i < num_files; i++)
{
len = DragQueryFile (hdrop, i, NULL, 0);
if (len <= 0)
continue;
name = alloca (len + 1);
DragQueryFile (hdrop, i, name, len + 1);
files = Fcons (DECODE_FILE (build_string (name)), files);
}
DragFinish (hdrop);
XSETFRAME (frame, f);
result->frame_or_window = frame;
result->arg = files;
return Qnil;
}
static MSG last_mouse_motion_event;
static Lisp_Object last_mouse_motion_frame;
static int
note_mouse_movement (frame, msg)
FRAME_PTR frame;
MSG *msg;
{
int mouse_x = LOWORD (msg->lParam);
int mouse_y = HIWORD (msg->lParam);
last_mouse_movement_time = msg->time;
memcpy (&last_mouse_motion_event, msg, sizeof (last_mouse_motion_event));
XSETFRAME (last_mouse_motion_frame, frame);
if (msg->hwnd != FRAME_W32_WINDOW (frame))
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, -1, -1);
last_mouse_glyph_frame = 0;
return 1;
}
if (frame != last_mouse_glyph_frame
|| mouse_x < last_mouse_glyph.left
|| mouse_x >= last_mouse_glyph.right
|| mouse_y < last_mouse_glyph.top
|| mouse_y >= last_mouse_glyph.bottom)
{
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, mouse_x, mouse_y);
remember_mouse_glyph (frame, mouse_x, mouse_y, &last_mouse_glyph);
last_mouse_glyph_frame = frame;
return 1;
}
return 0;
}
static struct scroll_bar *x_window_to_scroll_bar ();
static void x_scroll_bar_report_motion ();
static void x_check_fullscreen P_ ((struct frame *));
static void
redo_mouse_highlight ()
{
if (!NILP (last_mouse_motion_frame)
&& FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
note_mouse_highlight (XFRAME (last_mouse_motion_frame),
LOWORD (last_mouse_motion_event.lParam),
HIWORD (last_mouse_motion_event.lParam));
}
void
w32_define_cursor (window, cursor)
Window window;
Cursor cursor;
{
PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
}
static void
w32_mouse_position (fp, insist, bar_window, part, x, y, time)
FRAME_PTR *fp;
int insist;
Lisp_Object *bar_window;
enum scroll_bar_part *part;
Lisp_Object *x, *y;
unsigned long *time;
{
FRAME_PTR f1;
BLOCK_INPUT;
if (! NILP (last_mouse_scroll_bar) && insist == 0)
x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
else
{
POINT pt;
Lisp_Object frame, tail;
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->mouse_moved = 0;
last_mouse_scroll_bar = Qnil;
GetCursorPos (&pt);
{
if (FRAME_W32_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
{
f1 = last_mouse_frame;
}
else
{
f1 = x_any_window_to_frame (FRAME_W32_DISPLAY_INFO (*fp),
WindowFromPoint (pt));
}
if (! f1)
{
struct scroll_bar *bar
= x_window_to_scroll_bar (WindowFromPoint (pt));
if (bar)
{
f1 = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
}
}
if (f1 == 0 && insist > 0)
f1 = SELECTED_FRAME ();
if (f1)
{
ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
last_mouse_glyph_frame = f1;
*bar_window = Qnil;
*part = 0;
*fp = f1;
XSETINT (*x, pt.x);
XSETINT (*y, pt.y);
*time = last_mouse_movement_time;
}
}
}
UNBLOCK_INPUT;
}
static void
w32_handle_tool_bar_click (f, button_event)
struct frame *f;
struct input_event *button_event;
{
int x = XFASTINT (button_event->x);
int y = XFASTINT (button_event->y);
if (button_event->modifiers & down_modifier)
handle_tool_bar_click (f, x, y, 1, 0);
else
handle_tool_bar_click (f, x, y, 0,
button_event->modifiers & ~up_modifier);
}
static struct scroll_bar *
x_window_to_scroll_bar (window_id)
Window window_id;
{
Lisp_Object tail;
for (tail = Vframe_list;
XGCTYPE (tail) == Lisp_Cons;
tail = XCDR (tail))
{
Lisp_Object frame, bar, condemned;
frame = XCAR (tail);
if (! GC_FRAMEP (frame))
abort ();
condemned = FRAME_CONDEMNED_SCROLL_BARS (XFRAME (frame));
for (bar = FRAME_SCROLL_BARS (XFRAME (frame));
! GC_NILP (bar) || (bar = condemned,
condemned = Qnil,
! GC_NILP (bar));
bar = XSCROLL_BAR (bar)->next)
if (SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar)) == window_id)
return XSCROLL_BAR (bar);
}
return 0;
}
static void
w32_set_scroll_bar_thumb (bar, portion, position, whole)
struct scroll_bar *bar;
int portion, position, whole;
{
Window w = SCROLL_BAR_W32_WINDOW (bar);
double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height))
+ VERTICAL_SCROLL_BAR_MIN_HANDLE;
int sb_page, sb_pos;
BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
SCROLLINFO si;
if (draggingp)
{
int near_bottom_p;
BLOCK_INPUT;
si.cbSize = sizeof (si);
si.fMask = SIF_POS | SIF_PAGE;
GetScrollInfo(w, SB_CTL, &si);
near_bottom_p = si.nPos + si.nPage >= range;
UNBLOCK_INPUT;
if (!near_bottom_p)
return;
}
if (whole)
{
if (position + portion >= whole && !draggingp)
{
sb_page = range * (whole - position) / whole;
sb_pos = range;
}
else
{
sb_pos = position * range / whole;
sb_page = (min (portion, (whole - position)) * range) / whole;
}
}
else
{
sb_page = range;
sb_pos = 0;
}
sb_page = max (sb_page, VERTICAL_SCROLL_BAR_MIN_HANDLE);
BLOCK_INPUT;
si.cbSize = sizeof (si);
si.fMask = SIF_PAGE | SIF_POS;
si.nPage = sb_page;
si.nPos = sb_pos;
SetScrollInfo (w, SB_CTL, &si, TRUE);
UNBLOCK_INPUT;
}
HWND
my_create_scrollbar (f, bar)
struct frame * f;
struct scroll_bar * bar;
{
return (HWND) SendMessage (FRAME_W32_WINDOW (f),
WM_EMACS_CREATESCROLLBAR, (WPARAM) f,
(LPARAM) bar);
}
static BOOL
my_show_window (FRAME_PTR f, HWND hwnd, int how)
{
#ifndef ATTACH_THREADS
return SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SHOWWINDOW,
(WPARAM) hwnd, (LPARAM) how);
#else
return ShowWindow (hwnd, how);
#endif
}
static void
my_set_window_pos (HWND hwnd, HWND hwndAfter,
int x, int y, int cx, int cy, UINT flags)
{
#ifndef ATTACH_THREADS
WINDOWPOS pos;
pos.hwndInsertAfter = hwndAfter;
pos.x = x;
pos.y = y;
pos.cx = cx;
pos.cy = cy;
pos.flags = flags;
SendMessage (hwnd, WM_EMACS_SETWINDOWPOS, (WPARAM) &pos, 0);
#else
SetWindowPos (hwnd, hwndAfter, x, y, cx, cy, flags);
#endif
}
static void
my_set_focus (f, hwnd)
struct frame * f;
HWND hwnd;
{
SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_SETFOCUS,
(WPARAM) hwnd, 0);
}
static void
my_set_foreground_window (hwnd)
HWND hwnd;
{
SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
}
static void
my_destroy_window (f, hwnd)
struct frame * f;
HWND hwnd;
{
SendMessage (FRAME_W32_WINDOW (f), WM_EMACS_DESTROYWINDOW,
(WPARAM) hwnd, 0);
}
static struct scroll_bar *
x_scroll_bar_create (w, top, left, width, height)
struct window *w;
int top, left, width, height;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
HWND hwnd;
SCROLLINFO si;
struct scroll_bar *bar
= XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
BLOCK_INPUT;
XSETWINDOW (bar->window, w);
XSETINT (bar->top, top);
XSETINT (bar->left, left);
XSETINT (bar->width, width);
XSETINT (bar->height, height);
XSETINT (bar->start, 0);
XSETINT (bar->end, 0);
bar->dragging = Qnil;
hwnd = my_create_scrollbar (f, bar);
si.cbSize = sizeof (si);
si.fMask = SIF_ALL;
si.nMin = 0;
si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
+ VERTICAL_SCROLL_BAR_MIN_HANDLE;
si.nPage = si.nMax;
si.nPos = 0;
SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
bar->next = FRAME_SCROLL_BARS (f);
bar->prev = Qnil;
XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
if (! NILP (bar->next))
XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
UNBLOCK_INPUT;
return bar;
}
static void
x_scroll_bar_remove (bar)
struct scroll_bar *bar;
{
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
BLOCK_INPUT;
my_destroy_window (f, SCROLL_BAR_W32_WINDOW (bar));
XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
UNBLOCK_INPUT;
}
static void
w32_set_vertical_scroll_bar (w, portion, whole, position)
struct window *w;
int portion, whole, position;
{
struct frame *f = XFRAME (w->frame);
struct scroll_bar *bar;
int top, height, left, sb_left, width, sb_width;
int window_y, window_height;
window_box (w, -1, 0, &window_y, 0, &window_height);
top = window_y;
width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
height = window_height;
left = WINDOW_SCROLL_BAR_AREA_X (w);
if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
else
sb_width = width;
if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
sb_left = left + width - sb_width - (width - sb_width) / 2;
else
sb_left = left + (width - sb_width) / 2;
if (NILP (w->vertical_scroll_bar))
{
HDC hdc;
BLOCK_INPUT;
if (width > 0 && height > 0)
{
hdc = get_frame_dc (f);
w32_clear_area (f, hdc, left, top, width, height);
release_frame_dc (f, hdc);
}
UNBLOCK_INPUT;
bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
}
else
{
HWND hwnd;
bar = XSCROLL_BAR (w->vertical_scroll_bar);
hwnd = SCROLL_BAR_W32_WINDOW (bar);
if ( XINT (bar->left) == sb_left
&& XINT (bar->top) == top
&& XINT (bar->width) == sb_width
&& XINT (bar->height) == height )
{
if (!my_show_window (f, hwnd, SW_NORMAL))
InvalidateRect (hwnd, NULL, FALSE);
}
else
{
HDC hdc;
SCROLLINFO si;
BLOCK_INPUT;
if (width && height)
{
hdc = get_frame_dc (f);
w32_clear_area (f, hdc,
left,
top,
width,
height);
release_frame_dc (f, hdc);
}
my_show_window (f, hwnd, SW_HIDE);
MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
max (height, 1), TRUE);
si.cbSize = sizeof (si);
si.fMask = SIF_RANGE;
si.nMin = 0;
si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
+ VERTICAL_SCROLL_BAR_MIN_HANDLE;
SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
my_show_window (f, hwnd, SW_NORMAL);
XSETINT (bar->left, sb_left);
XSETINT (bar->top, top);
XSETINT (bar->width, sb_width);
XSETINT (bar->height, height);
UNBLOCK_INPUT;
}
}
w32_set_scroll_bar_thumb (bar, portion, position, whole);
XSETVECTOR (w->vertical_scroll_bar, bar);
}
static void
w32_condemn_scroll_bars (frame)
FRAME_PTR frame;
{
while (! NILP (FRAME_SCROLL_BARS (frame)))
{
Lisp_Object bar;
bar = FRAME_SCROLL_BARS (frame);
FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
XSCROLL_BAR (bar)->prev = Qnil;
if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
}
}
static void
w32_redeem_scroll_bar (window)
struct window *window;
{
struct scroll_bar *bar;
struct frame *f;
if (NILP (window->vertical_scroll_bar))
abort ();
bar = XSCROLL_BAR (window->vertical_scroll_bar);
f = XFRAME (WINDOW_FRAME (window));
if (NILP (bar->prev))
{
if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
return;
else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
window->vertical_scroll_bar))
FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
else
abort ();
}
else
XSCROLL_BAR (bar->prev)->next = bar->next;
if (! NILP (bar->next))
XSCROLL_BAR (bar->next)->prev = bar->prev;
bar->next = FRAME_SCROLL_BARS (f);
bar->prev = Qnil;
XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
if (! NILP (bar->next))
XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
}
static void
w32_judge_scroll_bars (f)
FRAME_PTR f;
{
Lisp_Object bar, next;
bar = FRAME_CONDEMNED_SCROLL_BARS (f);
FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
for (; ! NILP (bar); bar = next)
{
struct scroll_bar *b = XSCROLL_BAR (bar);
x_scroll_bar_remove (b);
next = b->next;
b->next = b->prev = Qnil;
}
}
static int
w32_scroll_bar_handle_click (bar, msg, emacs_event)
struct scroll_bar *bar;
W32Msg *msg;
struct input_event *emacs_event;
{
if (! GC_WINDOWP (bar->window))
abort ();
emacs_event->kind = W32_SCROLL_BAR_CLICK_EVENT;
emacs_event->code = 0;
emacs_event->modifiers = msg->dwModifiers;
emacs_event->frame_or_window = bar->window;
emacs_event->arg = Qnil;
emacs_event->timestamp = msg->msg.time;
{
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
int y;
int dragging = !NILP (bar->dragging);
SCROLLINFO si;
si.cbSize = sizeof (si);
si.fMask = SIF_POS;
GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
y = si.nPos;
bar->dragging = Qnil;
last_mouse_scroll_bar_pos = msg->msg.wParam;
switch (LOWORD (msg->msg.wParam))
{
case SB_LINEDOWN:
emacs_event->part = scroll_bar_down_arrow;
break;
case SB_LINEUP:
emacs_event->part = scroll_bar_up_arrow;
break;
case SB_PAGEUP:
emacs_event->part = scroll_bar_above_handle;
break;
case SB_PAGEDOWN:
emacs_event->part = scroll_bar_below_handle;
break;
case SB_TOP:
emacs_event->part = scroll_bar_handle;
y = 0;
break;
case SB_BOTTOM:
emacs_event->part = scroll_bar_handle;
y = top_range;
break;
case SB_THUMBTRACK:
case SB_THUMBPOSITION:
if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
y = HIWORD (msg->msg.wParam);
bar->dragging = Qt;
emacs_event->part = scroll_bar_handle;
{
SCROLLINFO si;
si.cbSize = sizeof (si);
si.fMask = SIF_POS;
si.nPos = y;
last_scroll_bar_drag_pos = y;
SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
}
break;
case SB_ENDSCROLL:
if (dragging)
{
SCROLLINFO si;
int start = XINT (bar->start);
int end = XINT (bar->end);
si.cbSize = sizeof (si);
si.fMask = SIF_PAGE | SIF_POS;
si.nPage = end - start + VERTICAL_SCROLL_BAR_MIN_HANDLE;
si.nPos = last_scroll_bar_drag_pos;
SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
}
default:
emacs_event->kind = NO_EVENT;
return FALSE;
}
XSETINT (emacs_event->x, y);
XSETINT (emacs_event->y, top_range);
return TRUE;
}
}
static void
x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
FRAME_PTR *fp;
Lisp_Object *bar_window;
enum scroll_bar_part *part;
Lisp_Object *x, *y;
unsigned long *time;
{
struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
Window w = SCROLL_BAR_W32_WINDOW (bar);
FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
int pos;
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
SCROLLINFO si;
BLOCK_INPUT;
*fp = f;
*bar_window = bar->window;
si.cbSize = sizeof (si);
si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
GetScrollInfo (w, SB_CTL, &si);
pos = si.nPos;
top_range = si.nMax - si.nPage + 1;
switch (LOWORD (last_mouse_scroll_bar_pos))
{
case SB_THUMBPOSITION:
case SB_THUMBTRACK:
*part = scroll_bar_handle;
if (VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)) <= 0xffff)
pos = HIWORD (last_mouse_scroll_bar_pos);
break;
case SB_LINEDOWN:
*part = scroll_bar_handle;
pos++;
break;
default:
*part = scroll_bar_handle;
break;
}
XSETINT (*x, pos);
XSETINT (*y, top_range);
f->mouse_moved = 0;
last_mouse_scroll_bar = Qnil;
*time = last_mouse_movement_time;
UNBLOCK_INPUT;
}
void
x_scroll_bar_clear (f)
FRAME_PTR f;
{
Lisp_Object bar;
if (FRAME_HAS_VERTICAL_SCROLL_BARS (f))
for (bar = FRAME_SCROLL_BARS (f); VECTORP (bar);
bar = XSCROLL_BAR (bar)->next)
{
HWND window = SCROLL_BAR_W32_WINDOW (XSCROLL_BAR (bar));
HDC hdc = GetDC (window);
RECT rect;
my_show_window (f, window, SW_HIDE);
GetClientRect (window, &rect);
select_palette (f, hdc);
w32_clear_rect (f, hdc, &rect);
deselect_palette (f, hdc);
ReleaseDC (window, hdc);
}
}
static int temp_index;
static short temp_buffer[100];
int
w32_read_socket (sd, expected, hold_quit)
register int sd;
int expected;
struct input_event *hold_quit;
{
int count = 0;
int check_visibility = 0;
W32Msg msg;
struct frame *f;
struct w32_display_info *dpyinfo = &one_w32_display_info;
if (interrupt_input_blocked)
{
interrupt_input_pending = 1;
return -1;
}
interrupt_input_pending = 0;
BLOCK_INPUT;
input_signal_count++;
while (get_next_msg (&msg, FALSE))
{
struct input_event inev;
int do_help = 0;
EVENT_INIT (inev);
inev.kind = NO_EVENT;
inev.arg = Qnil;
switch (msg.msg.message)
{
case WM_PAINT:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
if (msg.rect.right == msg.rect.left ||
msg.rect.bottom == msg.rect.top)
{
DebPrint (("clipped frame %p (%s) got WM_PAINT - ignored\n", f,
SDATA (f->name)));
}
else if (f->async_visible != 1)
{
f->async_visible = 1;
f->async_iconified = 0;
SET_FRAME_GARBAGED (f);
DebPrint (("frame %p (%s) reexposed by WM_PAINT\n", f,
SDATA (f->name)));
if (f->iconified)
{
inev.kind = DEICONIFY_EVENT;
XSETFRAME (inev.frame_or_window, f);
}
else if (! NILP (Vframe_list)
&& ! NILP (XCDR (Vframe_list)))
record_asynch_buffer_change ();
}
else
{
HDC hdc = get_frame_dc (f);
w32_clear_rect (f, hdc, &msg.rect);
release_frame_dc (f, hdc);
expose_frame (f,
msg.rect.left,
msg.rect.top,
msg.rect.right - msg.rect.left,
msg.rect.bottom - msg.rect.top);
}
}
break;
case WM_INPUTLANGCHANGE:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
inev.kind = LANGUAGE_CHANGE_EVENT;
XSETFRAME (inev.frame_or_window, f);
inev.code = msg.msg.wParam;
inev.modifiers = msg.msg.lParam & 0xffff;
}
break;
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f && !f->iconified)
{
if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
&& !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
{
clear_mouse_face (dpyinfo);
dpyinfo->mouse_face_hidden = 1;
}
if (temp_index == sizeof temp_buffer / sizeof (short))
temp_index = 0;
temp_buffer[temp_index++] = msg.msg.wParam;
inev.kind = NON_ASCII_KEYSTROKE_EVENT;
inev.code = msg.msg.wParam;
inev.modifiers = msg.dwModifiers;
XSETFRAME (inev.frame_or_window, f);
inev.timestamp = msg.msg.time;
}
break;
case WM_SYSCHAR:
case WM_CHAR:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f && !f->iconified)
{
if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight)
&& !EQ (f->tool_bar_window, dpyinfo->mouse_face_window))
{
clear_mouse_face (dpyinfo);
dpyinfo->mouse_face_hidden = 1;
}
if (temp_index == sizeof temp_buffer / sizeof (short))
temp_index = 0;
temp_buffer[temp_index++] = msg.msg.wParam;
inev.kind = ASCII_KEYSTROKE_EVENT;
inev.code = msg.msg.wParam;
inev.modifiers = msg.dwModifiers;
XSETFRAME (inev.frame_or_window, f);
inev.timestamp = msg.msg.time;
}
break;
case WM_MOUSEMOVE:
{
int x = LOWORD (msg.msg.lParam);
int y = HIWORD (msg.msg.lParam);
if (x == last_mousemove_x && y == last_mousemove_y)
break;
last_mousemove_x = x;
last_mousemove_y = y;
}
previous_help_echo_string = help_echo_string;
help_echo_string = Qnil;
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
f = last_mouse_frame;
else
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (dpyinfo->mouse_face_hidden)
{
dpyinfo->mouse_face_hidden = 0;
clear_mouse_face (dpyinfo);
}
if (f)
{
if (!NILP (Vmouse_autoselect_window))
{
Lisp_Object window;
int x = LOWORD (msg.msg.lParam);
int y = HIWORD (msg.msg.lParam);
window = window_from_coordinates (f, x, y, 0, 0, 0, 0);
if (WINDOWP(window)
&& !EQ (window, last_window)
&& !EQ (window, selected_window))
{
inev.kind = SELECT_WINDOW_EVENT;
inev.frame_or_window = window;
}
last_window=window;
}
if (!note_mouse_movement (f, &msg.msg))
help_echo_string = previous_help_echo_string;
}
else
{
clear_mouse_face (dpyinfo);
}
#if 0
if (help_echo_string != previous_help_echo_string ||
(!NILP (help_echo_string) && !STRINGP (help_echo_string) && f->mouse_moved))
#else
if (!NILP (help_echo_string)
|| !NILP (previous_help_echo_string))
do_help = 1;
#endif
break;
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_XBUTTONDOWN:
case WM_XBUTTONUP:
{
int tool_bar_p = 0;
int button;
int up;
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
f = last_mouse_frame;
else
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
construct_mouse_click (&inev, &msg, f);
if (WINDOWP (f->tool_bar_window)
&& WINDOW_TOTAL_LINES (XWINDOW (f->tool_bar_window)))
{
Lisp_Object window;
int x = XFASTINT (inev.x);
int y = XFASTINT (inev.y);
window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
if (EQ (window, f->tool_bar_window))
{
w32_handle_tool_bar_click (f, &inev);
tool_bar_p = 1;
}
}
if (tool_bar_p
|| (dpyinfo->w32_focus_frame
&& f != dpyinfo->w32_focus_frame))
inev.kind = NO_EVENT;
}
parse_button (msg.msg.message, HIWORD (msg.msg.wParam),
&button, &up);
if (up)
{
dpyinfo->grabbed &= ~ (1 << button);
}
else
{
dpyinfo->grabbed |= (1 << button);
last_mouse_frame = f;
if (f != 0)
f->mouse_moved = 0;
if (!tool_bar_p)
last_tool_bar_item = -1;
}
break;
}
case WM_MOUSEWHEEL:
{
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
f = last_mouse_frame;
else
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
if (!dpyinfo->w32_focus_frame
|| f == dpyinfo->w32_focus_frame)
{
construct_mouse_wheel (&inev, &msg, f);
}
f->mouse_moved = 0;
}
last_mouse_frame = f;
last_tool_bar_item = -1;
}
break;
case WM_DROPFILES:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
construct_drag_n_drop (&inev, &msg, f);
break;
case WM_VSCROLL:
{
struct scroll_bar *bar =
x_window_to_scroll_bar ((HWND)msg.msg.lParam);
if (bar)
w32_scroll_bar_handle_click (bar, &msg, &inev);
break;
}
case WM_WINDOWPOSCHANGED:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
if (f->want_fullscreen & FULLSCREEN_WAIT)
f->want_fullscreen &= ~(FULLSCREEN_WAIT|FULLSCREEN_BOTH);
}
check_visibility = 1;
break;
case WM_ACTIVATE:
case WM_ACTIVATEAPP:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
x_check_fullscreen (f);
check_visibility = 1;
break;
case WM_MOVE:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f && !f->async_iconified)
{
int x, y;
x_real_positions (f, &x, &y);
f->left_pos = x;
f->top_pos = y;
}
check_visibility = 1;
break;
case WM_SHOWWINDOW:
if (!msg.msg.wParam && msg.msg.hwnd == tip_window)
{
tip_window = NULL;
redo_mouse_highlight ();
}
#if 0
if (msg.msg.lParam != 0)
check_visibility = 1;
else
{
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
f->async_visible = msg.msg.wParam;
}
#endif
check_visibility = 1;
break;
case WM_SIZE:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
switch (msg.msg.wParam)
{
case SIZE_MINIMIZED:
f->async_visible = 0;
f->async_iconified = 1;
inev.kind = ICONIFY_EVENT;
XSETFRAME (inev.frame_or_window, f);
break;
case SIZE_MAXIMIZED:
case SIZE_RESTORED:
f->async_visible = 1;
f->async_iconified = 0;
SET_FRAME_GARBAGED (f);
if (f->iconified)
{
int x, y;
x_real_positions (f, &x, &y);
f->left_pos = x;
f->top_pos = y;
inev.kind = DEICONIFY_EVENT;
XSETFRAME (inev.frame_or_window, f);
}
else if (! NILP (Vframe_list)
&& ! NILP (XCDR (Vframe_list)))
record_asynch_buffer_change ();
break;
}
}
if (f && !f->async_iconified && msg.msg.wParam != SIZE_MINIMIZED)
{
RECT rect;
int rows;
int columns;
int width;
int height;
GetClientRect (msg.msg.hwnd, &rect);
height = rect.bottom - rect.top;
width = rect.right - rect.left;
rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
if (columns != FRAME_COLS (f)
|| rows != FRAME_LINES (f)
|| width != FRAME_PIXEL_WIDTH (f)
|| height != FRAME_PIXEL_HEIGHT (f))
{
change_frame_size (f, rows, columns, 0, 1, 0);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
FRAME_PIXEL_WIDTH (f) = width;
FRAME_PIXEL_HEIGHT (f) = height;
f->win_gravity = NorthWestGravity;
}
}
check_visibility = 1;
break;
case WM_MOUSELEAVE:
f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
if (f == dpyinfo->mouse_face_mouse_frame)
{
clear_mouse_face (dpyinfo);
dpyinfo->mouse_face_mouse_frame = 0;
}
if (any_help_event_p)
do_help = -1;
}
break;
case WM_SETFOCUS:
w32_detect_focus_change (dpyinfo, &msg, &inev);
dpyinfo->grabbed = 0;
check_visibility = 1;
break;
case WM_KILLFOCUS:
f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
if (f == dpyinfo->w32_focus_event_frame)
dpyinfo->w32_focus_event_frame = 0;
if (f == dpyinfo->w32_focus_frame)
x_new_focus_frame (dpyinfo, 0);
if (f == dpyinfo->mouse_face_mouse_frame)
{
clear_mouse_face (dpyinfo);
dpyinfo->mouse_face_mouse_frame = 0;
}
if (any_help_event_p)
do_help = -1;
}
dpyinfo->grabbed = 0;
check_visibility = 1;
break;
case WM_CLOSE:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
inev.kind = DELETE_WINDOW_EVENT;
XSETFRAME (inev.frame_or_window, f);
}
break;
case WM_INITMENU:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
inev.kind = MENU_BAR_ACTIVATE_EVENT;
XSETFRAME (inev.frame_or_window, f);
}
break;
case WM_COMMAND:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
extern void menubar_selection_callback
(FRAME_PTR f, void * client_data);
menubar_selection_callback (f, (void *)msg.msg.wParam);
}
check_visibility = 1;
break;
case WM_DISPLAYCHANGE:
f = x_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
{
dpyinfo->width = (short) LOWORD (msg.msg.lParam);
dpyinfo->height = (short) HIWORD (msg.msg.lParam);
dpyinfo->n_cbits = msg.msg.wParam;
DebPrint (("display change: %d %d\n", dpyinfo->width,
dpyinfo->height));
}
check_visibility = 1;
break;
default:
if (msg.msg.message == msh_mousewheel)
{
msg.msg.message = WM_MOUSEWHEEL;
prepend_msg (&msg);
}
break;
}
if (inev.kind != NO_EVENT)
{
kbd_buffer_store_event_hold (&inev, hold_quit);
count++;
}
if (do_help
&& !(hold_quit && hold_quit->kind != NO_EVENT))
{
Lisp_Object frame;
if (f)
XSETFRAME (frame, f);
else
frame = Qnil;
if (do_help > 0)
{
if (NILP (help_echo_string))
{
help_echo_object = help_echo_window = Qnil;
help_echo_pos = -1;
}
any_help_event_p = 1;
gen_help_event (help_echo_string, frame, help_echo_window,
help_echo_object, help_echo_pos);
}
else
{
help_echo_string = Qnil;
gen_help_event (Qnil, frame, Qnil, Qnil, 0);
}
count++;
}
}
if (pending_autoraise_frame)
{
x_raise_frame (pending_autoraise_frame);
pending_autoraise_frame = 0;
}
if (count > 0 || check_visibility)
{
Lisp_Object tail, frame;
FOR_EACH_FRAME (tail, frame)
{
FRAME_PTR f = XFRAME (frame);
if (EQ (frame, tip_frame))
continue;
if (FRAME_W32_P (f) && f->async_visible)
{
RECT clipbox;
HDC hdc;
enter_crit ();
hdc = GetWindowDC (FRAME_W32_WINDOW (f));
GetClipBox (hdc, &clipbox);
ReleaseDC (FRAME_W32_WINDOW (f), hdc);
leave_crit ();
if (clipbox.right == clipbox.left
|| clipbox.bottom == clipbox.top)
{
f->async_visible = 2;
if (!FRAME_OBSCURED_P (f))
{
DebPrint (("frame %p (%s) obscured\n", f,
SDATA (f->name)));
}
}
else
{
f->async_visible = 1;
if (FRAME_OBSCURED_P (f))
{
SET_FRAME_GARBAGED (f);
DebPrint (("obscured frame %p (%s) found to be visible\n", f,
SDATA (f->name)));
record_asynch_buffer_change ();
}
}
}
}
}
UNBLOCK_INPUT;
return count;
}
static void
w32_clip_to_row (w, row, area, hdc)
struct window *w;
struct glyph_row *row;
int area;
HDC hdc;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
RECT clip_rect;
int window_x, window_y, window_width;
window_box (w, area, &window_x, &window_y, &window_width, 0);
clip_rect.left = window_x;
clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
clip_rect.top = max (clip_rect.top, window_y);
clip_rect.right = clip_rect.left + window_width;
clip_rect.bottom = clip_rect.top + row->visible_height;
w32_set_clip_rectangle (hdc, &clip_rect);
}
static void
x_draw_hollow_cursor (w, row)
struct window *w;
struct glyph_row *row;
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
HDC hdc;
RECT rect;
int left, top, h;
struct glyph *cursor_glyph;
HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph == NULL)
return;
get_phys_cursor_geometry (w, row, cursor_glyph, &left, &top, &h);
rect.left = left;
rect.top = top;
rect.bottom = rect.top + h;
rect.right = rect.left + w->phys_cursor_width;
hdc = get_frame_dc (f);
w32_clip_to_row (w, row, TEXT_AREA, hdc);
FrameRect (hdc, &rect, hb);
DeleteObject (hb);
w32_set_clip_rectangle (hdc, NULL);
release_frame_dc (f, hdc);
}
static void
x_draw_bar_cursor (w, row, width, kind)
struct window *w;
struct glyph_row *row;
int width;
enum text_cursor_kinds kind;
{
struct frame *f = XFRAME (w->frame);
struct glyph *cursor_glyph;
int x;
HDC hdc;
cursor_glyph = get_phys_cursor_glyph (w);
if (cursor_glyph == NULL)
return;
if (cursor_glyph->type == IMAGE_GLYPH)
{
struct glyph_row *row;
row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
}
else
{
COLORREF cursor_color = f->output_data.w32->cursor_pixel;
struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
if (face->background == cursor_color)
cursor_color = face->foreground;
x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
if (width < 0)
width = FRAME_CURSOR_WIDTH (f);
width = min (cursor_glyph->pixel_width, width);
w->phys_cursor_width = width;
hdc = get_frame_dc (f);
w32_clip_to_row (w, row, TEXT_AREA, hdc);
if (kind == BAR_CURSOR)
{
w32_fill_area (f, hdc, cursor_color, x,
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
width, row->height);
}
else
{
w32_fill_area (f, hdc, cursor_color, x,
WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
row->height - width),
cursor_glyph->pixel_width, width);
}
w32_set_clip_rectangle (hdc, NULL);
release_frame_dc (f, hdc);
}
}
static void
w32_define_frame_cursor (f, cursor)
struct frame *f;
Cursor cursor;
{
w32_define_cursor (FRAME_W32_WINDOW (f), cursor);
}
static void
w32_clear_frame_area (f, x, y, width, height)
struct frame *f;
int x, y, width, height;
{
HDC hdc;
hdc = get_frame_dc (f);
w32_clear_area (f, hdc, x, y, width, height);
release_frame_dc (f, hdc);
}
static void
w32_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
struct window *w;
struct glyph_row *glyph_row;
int x, y;
int cursor_type, cursor_width;
int on_p, active_p;
{
if (on_p)
{
if (w32_use_visible_system_caret)
{
if (w->phys_cursor_type != NO_CURSOR)
erase_phys_cursor (w);
cursor_type = w->phys_cursor_type = NO_CURSOR;
w->phys_cursor_width = -1;
}
else
{
w->phys_cursor_type = cursor_type;
}
w->phys_cursor_on_p = 1;
if (active_p)
{
struct frame *f = XFRAME (WINDOW_FRAME (w));
HWND hwnd = FRAME_W32_WINDOW (f);
w32_system_caret_x
= WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
w32_system_caret_y
= (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
+ glyph_row->ascent - w->phys_cursor_ascent);
if (w32_system_caret_hwnd
&& (w32_system_caret_height != w->phys_cursor_height))
PostMessage (hwnd, WM_EMACS_DESTROY_CARET, 0, 0);
w32_system_caret_height = w->phys_cursor_height;
PostMessage (hwnd, WM_EMACS_TRACK_CARET, 0, 0);
}
if (glyph_row->exact_window_width_line_p
&& w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
{
glyph_row->cursor_in_fringe_p = 1;
draw_fringe_bitmap (w, glyph_row, 0);
return;
}
switch (cursor_type)
{
case HOLLOW_BOX_CURSOR:
x_draw_hollow_cursor (w, glyph_row);
break;
case FILLED_BOX_CURSOR:
draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
break;
case BAR_CURSOR:
x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
break;
case HBAR_CURSOR:
x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
break;
case NO_CURSOR:
w->phys_cursor_width = 0;
break;
default:
abort ();
}
}
}
int
x_bitmap_icon (f, icon)
struct frame *f;
Lisp_Object icon;
{
HANDLE main_icon;
HANDLE small_icon = NULL;
if (FRAME_W32_WINDOW (f) == 0)
return 1;
if (NILP (icon))
main_icon = LoadIcon (hinst, EMACS_CLASS);
else if (STRINGP (icon))
{
main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
LR_DEFAULTSIZE | LR_LOADFROMFILE);
small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
GetSystemMetrics (SM_CXSMICON),
GetSystemMetrics (SM_CYSMICON),
LR_LOADFROMFILE);
}
else if (SYMBOLP (icon))
{
LPCTSTR name;
if (EQ (icon, intern ("application")))
name = (LPCTSTR) IDI_APPLICATION;
else if (EQ (icon, intern ("hand")))
name = (LPCTSTR) IDI_HAND;
else if (EQ (icon, intern ("question")))
name = (LPCTSTR) IDI_QUESTION;
else if (EQ (icon, intern ("exclamation")))
name = (LPCTSTR) IDI_EXCLAMATION;
else if (EQ (icon, intern ("asterisk")))
name = (LPCTSTR) IDI_ASTERISK;
else if (EQ (icon, intern ("winlogo")))
name = (LPCTSTR) IDI_WINLOGO;
else
return 1;
main_icon = LoadIcon (NULL, name);
}
else
return 1;
if (main_icon == NULL)
return 1;
PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
(LPARAM) main_icon);
if (small_icon)
PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
(LPARAM) small_icon);
return 0;
}
Lisp_Object
x_new_font (f, fontname)
struct frame *f;
register char *fontname;
{
struct font_info *fontp
= FS_LOAD_FONT (f, 0, fontname, -1);
if (!fontp)
return Qnil;
FRAME_FONT (f) = (XFontStruct *) (fontp->font);
FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
FRAME_FONTSET (f) = -1;
FRAME_COLUMN_WIDTH (f) = fontp->average_width;
FRAME_SPACE_WIDTH (f) = fontp->space_width;
FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
compute_fringe_widths (f, 1);
if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
{
int wid = FRAME_COLUMN_WIDTH (f);
FRAME_CONFIG_SCROLL_BAR_COLS (f)
= (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
}
else
{
int wid = FRAME_COLUMN_WIDTH (f);
FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
}
if (FRAME_W32_WINDOW (f) != 0)
{
if (NILP (tip_frame) || XFRAME (tip_frame) != f)
x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
}
return build_string (fontp->full_name);
}
Lisp_Object
x_new_fontset (f, fontsetname)
struct frame *f;
char *fontsetname;
{
int fontset = fs_query_fontset (build_string (fontsetname), 0);
Lisp_Object result;
if (fontset < 0)
return Qnil;
if (FRAME_FONTSET (f) == fontset)
return fontset_name (fontset);
result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
if (!STRINGP (result))
return Qnil;
FRAME_FONTSET(f) = fontset;
return build_string (fontsetname);
}
void
x_calc_absolute_position (f)
struct frame *f;
{
int flags = f->size_hint_flags;
unsigned int left_right_borders_width, top_bottom_borders_height;
WINDOWPLACEMENT wp = { 0 };
RECT client_rect = { 0 };
if (GetWindowPlacement (FRAME_W32_WINDOW (f), &wp)
&& GetClientRect (FRAME_W32_WINDOW (f), &client_rect))
{
left_right_borders_width =
(wp.rcNormalPosition.right - wp.rcNormalPosition.left) -
(client_rect.right - client_rect.left);
top_bottom_borders_height =
(wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
(client_rect.bottom - client_rect.top);
}
else
{
left_right_borders_width = 8;
top_bottom_borders_height = 32;
}
if (flags & XNegative)
f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
- FRAME_PIXEL_WIDTH (f)
+ f->left_pos
- (left_right_borders_width - 1));
if (flags & YNegative)
f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
- FRAME_PIXEL_HEIGHT (f)
+ f->top_pos
- (top_bottom_borders_height - 1));
f->size_hint_flags &= ~ (XNegative | YNegative);
}
void
x_set_offset (f, xoff, yoff, change_gravity)
struct frame *f;
register int xoff, yoff;
int change_gravity;
{
int modified_top, modified_left;
if (change_gravity > 0)
{
f->top_pos = yoff;
f->left_pos = xoff;
f->size_hint_flags &= ~ (XNegative | YNegative);
if (xoff < 0)
f->size_hint_flags |= XNegative;
if (yoff < 0)
f->size_hint_flags |= YNegative;
f->win_gravity = NorthWestGravity;
}
x_calc_absolute_position (f);
BLOCK_INPUT;
x_wm_set_size_hint (f, (long) 0, 0);
modified_left = f->left_pos;
modified_top = f->top_pos;
my_set_window_pos (FRAME_W32_WINDOW (f),
NULL,
modified_left, modified_top,
0, 0,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE);
UNBLOCK_INPUT;
}
static void
x_check_fullscreen (f)
struct frame *f;
{
if (f->want_fullscreen & FULLSCREEN_BOTH)
{
int width, height, ign;
x_real_positions (f, &f->left_pos, &f->top_pos);
x_fullscreen_adjust (f, &width, &height, &ign, &ign);
if (FRAME_COLS (f) != width || FRAME_LINES (f) != height)
{
change_frame_size (f, height, width, 0, 1, 0);
SET_FRAME_GARBAGED (f);
cancel_mouse_face (f);
f->want_fullscreen |= FULLSCREEN_WAIT;
}
}
}
void
x_set_window_size (f, change_gravity, cols, rows)
struct frame *f;
int change_gravity;
int cols, rows;
{
int pixelwidth, pixelheight;
BLOCK_INPUT;
check_frame_size (f, &rows, &cols);
f->scroll_bar_actual_width
= FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
compute_fringe_widths (f, 0);
pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
f->win_gravity = NorthWestGravity;
x_wm_set_size_hint (f, (long) 0, 0);
{
RECT rect;
rect.left = rect.top = 0;
rect.right = pixelwidth;
rect.bottom = pixelheight;
AdjustWindowRect(&rect, f->output_data.w32->dwStyle,
FRAME_EXTERNAL_MENU_BAR (f));
my_set_window_pos (FRAME_W32_WINDOW (f),
NULL,
0, 0,
rect.right - rect.left,
rect.bottom - rect.top,
SWP_NOZORDER | SWP_NOMOVE | SWP_NOACTIVATE);
}
change_frame_size (f, rows, cols, 0, 1, 0);
FRAME_PIXEL_WIDTH (f) = pixelwidth;
FRAME_PIXEL_HEIGHT (f) = pixelheight;
SET_FRAME_GARBAGED (f);
mark_window_cursors_off (XWINDOW (f->root_window));
cancel_mouse_face (f);
UNBLOCK_INPUT;
}
void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
void
x_set_mouse_position (f, x, y)
struct frame *f;
int x, y;
{
int pix_x, pix_y;
pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
if (pix_x < 0) pix_x = 0;
if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
if (pix_y < 0) pix_y = 0;
if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
x_set_mouse_pixel_position (f, pix_x, pix_y);
}
void
x_set_mouse_pixel_position (f, pix_x, pix_y)
struct frame *f;
int pix_x, pix_y;
{
RECT rect;
POINT pt;
BLOCK_INPUT;
GetClientRect (FRAME_W32_WINDOW (f), &rect);
pt.x = rect.left + pix_x;
pt.y = rect.top + pix_y;
ClientToScreen (FRAME_W32_WINDOW (f), &pt);
SetCursorPos (pt.x, pt.y);
UNBLOCK_INPUT;
}
void
x_focus_on_frame (f)
struct frame *f;
{
struct w32_display_info *dpyinfo = &one_w32_display_info;
BLOCK_INPUT;
#if 0
if (x_window_to_frame (dpyinfo, GetForegroundWindow ()))
my_set_focus (f, FRAME_W32_WINDOW (f));
else
#endif
my_set_foreground_window (FRAME_W32_WINDOW (f));
UNBLOCK_INPUT;
}
void
x_unfocus_frame (f)
struct frame *f;
{
}
void
x_raise_frame (f)
struct frame *f;
{
BLOCK_INPUT;
if (NILP (Vw32_grab_focus_on_raise))
{
HDWP handle = BeginDeferWindowPos (2);
if (handle)
{
DeferWindowPos (handle,
FRAME_W32_WINDOW (f),
HWND_TOP,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
DeferWindowPos (handle,
GetForegroundWindow (),
FRAME_W32_WINDOW (f),
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
EndDeferWindowPos (handle);
}
}
else
{
my_set_foreground_window (FRAME_W32_WINDOW (f));
}
UNBLOCK_INPUT;
}
void
x_lower_frame (f)
struct frame *f;
{
BLOCK_INPUT;
my_set_window_pos (FRAME_W32_WINDOW (f),
HWND_BOTTOM,
0, 0, 0, 0,
SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE);
UNBLOCK_INPUT;
}
static void
w32_frame_raise_lower (f, raise_flag)
FRAME_PTR f;
int raise_flag;
{
if (! FRAME_W32_P (f))
return;
if (raise_flag)
x_raise_frame (f);
else
x_lower_frame (f);
}
void
x_make_frame_visible (f)
struct frame *f;
{
Lisp_Object type;
BLOCK_INPUT;
type = x_icon_type (f);
if (!NILP (type))
x_bitmap_icon (f, type);
if (! FRAME_VISIBLE_P (f))
{
if (! FRAME_ICONIFIED_P (f)
&& ! f->output_data.w32->asked_for_visible)
{
RECT workarea_rect;
RECT window_rect;
SystemParametersInfo(SPI_GETWORKAREA, 0, &workarea_rect, 0);
GetWindowRect(FRAME_W32_WINDOW(f), &window_rect);
if (window_rect.bottom > workarea_rect.bottom
&& window_rect.top > workarea_rect.top)
f->top_pos = max (window_rect.top
- window_rect.bottom + workarea_rect.bottom,
workarea_rect.top);
x_set_offset (f, f->left_pos, f->top_pos, 0);
}
f->output_data.w32->asked_for_visible = 1;
my_show_window (f, FRAME_W32_WINDOW (f), SW_SHOWNORMAL);
}
{
Lisp_Object frame;
int count;
UNBLOCK_INPUT;
XSETFRAME (frame, f);
for (count = input_signal_count + 10;
input_signal_count < count && !FRAME_VISIBLE_P (f);)
{
if (input_polling_used ())
{
int old_poll_suppress_count = poll_suppress_count;
poll_suppress_count = 1;
poll_for_input_1 ();
poll_suppress_count = old_poll_suppress_count;
}
}
FRAME_SAMPLE_VISIBILITY (f);
}
}
x_make_frame_invisible (f)
struct frame *f;
{
if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
BLOCK_INPUT;
my_show_window (f, FRAME_W32_WINDOW (f), SW_HIDE);
f->visible = 0;
FRAME_ICONIFIED_P (f) = 0;
f->async_visible = 0;
f->async_iconified = 0;
UNBLOCK_INPUT;
}
void
x_iconify_frame (f)
struct frame *f;
{
Lisp_Object type;
if (FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame == f)
FRAME_W32_DISPLAY_INFO (f)->x_highlight_frame = 0;
if (f->async_iconified)
return;
BLOCK_INPUT;
type = x_icon_type (f);
if (!NILP (type))
x_bitmap_icon (f, type);
SendMessage (FRAME_W32_WINDOW (f), WM_SYSCOMMAND, SC_MINIMIZE, 0);
UNBLOCK_INPUT;
}
void
x_free_frame_resources (f)
struct frame *f;
{
struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
BLOCK_INPUT;
if (FRAME_W32_WINDOW (f))
my_destroy_window (f, FRAME_W32_WINDOW (f));
free_frame_menubar (f);
unload_color (f, f->output_data.x->foreground_pixel);
unload_color (f, f->output_data.x->background_pixel);
unload_color (f, f->output_data.w32->cursor_pixel);
unload_color (f, f->output_data.w32->cursor_foreground_pixel);
unload_color (f, f->output_data.w32->border_pixel);
unload_color (f, f->output_data.w32->mouse_pixel);
if (f->output_data.w32->white_relief.allocated_p)
unload_color (f, f->output_data.w32->white_relief.pixel);
if (f->output_data.w32->black_relief.allocated_p)
unload_color (f, f->output_data.w32->black_relief.pixel);
if (FRAME_FACE_CACHE (f))
free_frame_faces (f);
xfree (f->output_data.w32);
f->output_data.w32 = NULL;
if (f == dpyinfo->w32_focus_frame)
dpyinfo->w32_focus_frame = 0;
if (f == dpyinfo->w32_focus_event_frame)
dpyinfo->w32_focus_event_frame = 0;
if (f == dpyinfo->x_highlight_frame)
dpyinfo->x_highlight_frame = 0;
if (f == dpyinfo->mouse_face_mouse_frame)
{
dpyinfo->mouse_face_beg_row
= dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row
= dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
dpyinfo->mouse_face_deferred_gc = 0;
dpyinfo->mouse_face_mouse_frame = 0;
}
UNBLOCK_INPUT;
}
x_destroy_window (f)
struct frame *f;
{
struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
x_free_frame_resources (f);
dpyinfo->reference_count--;
}
void
x_wm_set_size_hint (f, flags, user_position)
struct frame *f;
long flags;
int user_position;
{
Window window = FRAME_W32_WINDOW (f);
enter_crit ();
SetWindowLong (window, WND_FONTWIDTH_INDEX, FRAME_COLUMN_WIDTH (f));
SetWindowLong (window, WND_LINEHEIGHT_INDEX, FRAME_LINE_HEIGHT (f));
SetWindowLong (window, WND_BORDER_INDEX, FRAME_INTERNAL_BORDER_WIDTH (f));
SetWindowLong (window, WND_SCROLLBAR_INDEX, f->scroll_bar_actual_width);
leave_crit ();
}
void
x_wm_set_icon_position (f, icon_x, icon_y)
struct frame *f;
int icon_x, icon_y;
{
#if 0
Window window = FRAME_W32_WINDOW (f);
f->display.x->wm_hints.flags |= IconPositionHint;
f->display.x->wm_hints.icon_x = icon_x;
f->display.x->wm_hints.icon_y = icon_y;
XSetWMHints (FRAME_X_DISPLAY (f), window, &f->display.x->wm_hints);
#endif
}
#if GLYPH_DEBUG
static void
x_check_font (f, font)
struct frame *f;
XFontStruct *font;
{
int i;
struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
xassert (font != NULL);
for (i = 0; i < dpyinfo->n_fonts; i++)
if (dpyinfo->font_table[i].name
&& font == dpyinfo->font_table[i].font)
break;
xassert (i < dpyinfo->n_fonts);
}
#endif
static INLINE void
x_font_min_bounds (font, w, h)
XFontStruct *font;
int *w, *h;
{
*h = FONT_HEIGHT (font);
*w = FONT_WIDTH (font);
}
int
x_compute_min_glyph_bounds (f)
struct frame *f;
{
int i;
struct w32_display_info *dpyinfo = FRAME_W32_DISPLAY_INFO (f);
XFontStruct *font;
int old_width = dpyinfo->smallest_char_width;
int old_height = dpyinfo->smallest_font_height;
dpyinfo->smallest_font_height = 100000;
dpyinfo->smallest_char_width = 100000;
for (i = 0; i < dpyinfo->n_fonts; ++i)
if (dpyinfo->font_table[i].name)
{
struct font_info *fontp = dpyinfo->font_table + i;
int w, h;
font = (XFontStruct *) fontp->font;
xassert (font != (XFontStruct *) ~0);
x_font_min_bounds (font, &w, &h);
dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
}
xassert (dpyinfo->smallest_char_width > 0
&& dpyinfo->smallest_font_height > 0);
return (dpyinfo->n_fonts == 1
|| dpyinfo->smallest_char_width < old_width
|| dpyinfo->smallest_font_height < old_height);
}
static int w32_initialized = 0;
void
w32_initialize_display_info (display_name)
Lisp_Object display_name;
{
struct w32_display_info *dpyinfo = &one_w32_display_info;
bzero (dpyinfo, sizeof (*dpyinfo));
w32_display_name_list = Fcons (Fcons (display_name, Qnil),
w32_display_name_list);
dpyinfo->name_list_element = XCAR (w32_display_name_list);
dpyinfo->w32_id_name
= (char *) xmalloc (SCHARS (Vinvocation_name)
+ SCHARS (Vsystem_name)
+ 2);
sprintf (dpyinfo->w32_id_name, "%s@%s",
SDATA (Vinvocation_name), SDATA (Vsystem_name));
dpyinfo->resx = 1;
dpyinfo->resy = 1;
dpyinfo->height_in = 1;
dpyinfo->width_in = 1;
dpyinfo->n_planes = 1;
dpyinfo->n_cbits = 4;
dpyinfo->n_fonts = 0;
dpyinfo->smallest_font_height = 1;
dpyinfo->smallest_char_width = 1;
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
dpyinfo->mouse_face_window = Qnil;
dpyinfo->mouse_face_overlay = Qnil;
dpyinfo->mouse_face_hidden = 0;
dpyinfo->vertical_scroll_bar_cursor = w32_load_cursor (IDC_ARROW);
}
static char *
w32_make_rdb (xrm_option)
char *xrm_option;
{
char *buffer = xmalloc (strlen (xrm_option) + 2);
char *current = buffer;
char ch;
int in_option = 1;
int before_value = 0;
do {
ch = *xrm_option++;
if (ch == '\n')
{
*current++ = '\0';
in_option = 1;
before_value = 0;
}
else if (ch != ' ')
{
*current++ = ch;
if (in_option && (ch == ':'))
{
in_option = 0;
before_value = 1;
}
else if (before_value)
{
before_value = 0;
}
}
else if (!(in_option || before_value))
{
*current++ = ch;
}
} while (ch);
*current = '\0';
return buffer;
}
struct w32_display_info *
w32_term_init (display_name, xrm_option, resource_name)
Lisp_Object display_name;
char *xrm_option;
char *resource_name;
{
struct w32_display_info *dpyinfo;
HDC hdc;
BLOCK_INPUT;
if (!w32_initialized)
{
w32_initialize ();
w32_initialized = 1;
}
w32_initialize_display_info (display_name);
dpyinfo = &one_w32_display_info;
dpyinfo->xrdb = xrm_option ? w32_make_rdb (xrm_option) : NULL;
dpyinfo->next = x_display_list;
x_display_list = dpyinfo;
hdc = GetDC (GetDesktopWindow ());
dpyinfo->height = GetDeviceCaps (hdc, VERTRES);
dpyinfo->width = GetDeviceCaps (hdc, HORZRES);
dpyinfo->root_window = GetDesktopWindow ();
dpyinfo->n_planes = GetDeviceCaps (hdc, PLANES);
dpyinfo->n_cbits = GetDeviceCaps (hdc, BITSPIXEL);
dpyinfo->resx = GetDeviceCaps (hdc, LOGPIXELSX);
dpyinfo->resy = GetDeviceCaps (hdc, LOGPIXELSY);
dpyinfo->has_palette = GetDeviceCaps (hdc, RASTERCAPS) & RC_PALETTE;
dpyinfo->image_cache = make_image_cache ();
dpyinfo->height_in = dpyinfo->height / dpyinfo->resx;
dpyinfo->width_in = dpyinfo->width / dpyinfo->resy;
ReleaseDC (GetDesktopWindow (), hdc);
{
XColor color;
w32_defined_color (0, "white", &color, 1);
w32_defined_color (0, "black", &color, 1);
}
w32_init_fringe ();
#ifndef F_SETOWN_BUG
#ifdef F_SETOWN
#ifdef F_SETOWN_SOCK_NEG
fcntl (connection, F_SETOWN, -getpid ());
#else
fcntl (connection, F_SETOWN, getpid ());
#endif
#endif
#endif
#ifdef SIGIO
if (interrupt_input)
init_sigio (connection);
#endif
UNBLOCK_INPUT;
return dpyinfo;
}
void
x_delete_display (dpyinfo)
struct w32_display_info *dpyinfo;
{
if (! NILP (w32_display_name_list)
&& EQ (XCAR (w32_display_name_list), dpyinfo->name_list_element))
w32_display_name_list = XCDR (w32_display_name_list);
else
{
Lisp_Object tail;
tail = w32_display_name_list;
while (CONSP (tail) && CONSP (XCDR (tail)))
{
if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
{
XSETCDR (tail, XCDR (XCDR (tail)));
break;
}
tail = XCDR (tail);
}
}
{
struct w32_palette_entry * plist;
plist = dpyinfo->color_list;
while (plist)
{
struct w32_palette_entry * pentry = plist;
plist = plist->next;
xfree (pentry);
}
dpyinfo->color_list = NULL;
if (dpyinfo->palette)
DeleteObject(dpyinfo->palette);
}
xfree (dpyinfo->font_table);
xfree (dpyinfo->w32_id_name);
w32_reset_fringes ();
}
DWORD WINAPI w32_msg_worker (void * arg);
void
x_flush (struct frame * f)
{ }
extern frame_parm_handler w32_frame_parm_handlers[];
static struct redisplay_interface w32_redisplay_interface =
{
w32_frame_parm_handlers,
x_produce_glyphs,
x_write_glyphs,
x_insert_glyphs,
x_clear_end_of_line,
x_scroll_run,
x_after_update_window_line,
x_update_window_begin,
x_update_window_end,
x_cursor_to,
x_flush,
0,
x_clear_window_mouse_face,
w32_get_glyph_overhangs,
x_fix_overlapping_area,
w32_draw_fringe_bitmap,
w32_define_fringe_bitmap,
w32_destroy_fringe_bitmap,
w32_per_char_metric,
w32_encode_char,
NULL,
x_draw_glyph_string,
w32_define_frame_cursor,
w32_clear_frame_area,
w32_draw_window_cursor,
w32_draw_vertical_window_border,
w32_shift_glyphs_for_insert
};
void
w32_initialize ()
{
rif = &w32_redisplay_interface;
clear_frame_hook = (void (*)(void)) x_clear_frame;
ring_bell_hook = (void (*)(void)) w32_ring_bell;
update_begin_hook = x_update_begin;
update_end_hook = x_update_end;
read_socket_hook = w32_read_socket;
frame_up_to_date_hook = w32_frame_up_to_date;
mouse_position_hook = w32_mouse_position;
frame_rehighlight_hook = w32_frame_rehighlight;
frame_raise_lower_hook = w32_frame_raise_lower;
set_vertical_scroll_bar_hook = w32_set_vertical_scroll_bar;
condemn_scroll_bars_hook = w32_condemn_scroll_bars;
redeem_scroll_bar_hook = w32_redeem_scroll_bar;
judge_scroll_bars_hook = w32_judge_scroll_bars;
scroll_region_ok = 1;
char_ins_del_ok = 1;
line_ins_del_ok = 1;
fast_clear_end_of_line = 1;
memory_below_frame = 0;
baud_rate = 19200;
w32_system_caret_hwnd = NULL;
w32_system_caret_height = 0;
w32_system_caret_x = 0;
w32_system_caret_y = 0;
if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
&w32_use_visible_system_caret, 0))
w32_use_visible_system_caret = 0;
last_tool_bar_item = -1;
any_help_event_p = 0;
Fset_input_mode (Qnil, Qnil, make_number (2), Qnil);
init_crit ();
dwMainThreadId = GetCurrentThreadId ();
DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
GetCurrentProcess (), &hMainThread, 0, TRUE, DUPLICATE_SAME_ACCESS);
{
MSG msg;
PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
hWindowsThread = CreateThread (NULL, 0,
w32_msg_worker,
0, 0, &dwWindowsThreadId);
GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
}
#ifdef ATTACH_THREADS
AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
#endif
{
UINT smoothing_type;
BOOL smoothing_enabled;
vertical_scroll_bar_min_handle = 5;
vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
= GetSystemMetrics (SM_CYVSCROLL);
#ifndef SPI_GETFONTSMOOTHING
#define SPI_GETFONTSMOOTHING 0x4A
#endif
#ifndef SPI_GETFONTSMOOTHINGTYPE
#define SPI_GETFONTSMOOTHINGTYPE 0x0200A
#endif
#ifndef FE_FONTSMOOTHINGCLEARTYPE
#define FE_FONTSMOOTHINGCLEARTYPE 0x2
#endif
cleartype_active =
SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &smoothing_enabled, 0)
&& smoothing_enabled
&& SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)
&& smoothing_type == FE_FONTSMOOTHINGCLEARTYPE;
}
}
void
syms_of_w32term ()
{
staticpro (&w32_display_name_list);
w32_display_name_list = Qnil;
staticpro (&last_mouse_scroll_bar);
last_mouse_scroll_bar = Qnil;
staticpro (&Qvendor_specific_keysyms);
Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
DEFVAR_INT ("w32-num-mouse-buttons",
&w32_num_mouse_buttons,
doc: );
w32_num_mouse_buttons = 2;
DEFVAR_LISP ("w32-swap-mouse-buttons",
&Vw32_swap_mouse_buttons,
doc: );
Vw32_swap_mouse_buttons = Qnil;
DEFVAR_LISP ("w32-grab-focus-on-raise",
&Vw32_grab_focus_on_raise,
doc: );
Vw32_grab_focus_on_raise = Qt;
DEFVAR_LISP ("w32-capslock-is-shiftlock",
&Vw32_capslock_is_shiftlock,
doc: );
Vw32_capslock_is_shiftlock = Qnil;
DEFVAR_LISP ("w32-recognize-altgr",
&Vw32_recognize_altgr,
doc: );
Vw32_recognize_altgr = Qt;
DEFVAR_BOOL ("w32-enable-unicode-output",
&w32_enable_unicode_output,
doc: );
w32_enable_unicode_output = 1;
DEFVAR_BOOL ("w32-use-visible-system-caret",
&w32_use_visible_system_caret,
doc: );
w32_use_visible_system_caret = 0;
DEFVAR_BOOL ("x-use-underline-position-properties",
&x_use_underline_position_properties,
doc: );
x_use_underline_position_properties = 0;
DEFVAR_BOOL ("x-underline-at-descent-line",
&x_underline_at_descent_line,
doc: );
x_underline_at_descent_line = 0;
DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
doc: );
Vx_toolkit_scroll_bars = Qt;
staticpro (&last_mouse_motion_frame);
last_mouse_motion_frame = Qnil;
}