/* Implementation of GUI terminal on the Microsoft W32 API.
- Copyright (C) 1989, 93, 94, 95, 96, 1997, 1998, 1999, 2000, 2001
- Free Software Foundation, Inc.
+ Copyright (C) 1989, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
+ 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
This file is part of GNU Emacs.
You should have received a copy of the GNU General Public License
along with GNU Emacs; see the file COPYING. If not, write to
-the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA. */
+the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+Boston, MA 02110-1301, USA. */
#include <config.h>
#include <signal.h>
\f
/* Fringe bitmaps. */
-static HBITMAP fringe_bmp[MAX_FRINGE_BITMAPS];
+static int max_fringe_bmp = 0;
+static HBITMAP *fringe_bmp = 0;
/* Non-nil means Emacs uses toolkit scroll bars. */
/* Last window where we saw the mouse. Used by mouse-autoselect-window. */
static Lisp_Object last_window;
+/* Non-zero means make use of UNDERLINE_POSITION font properties.
+ (Not yet supported, see TODO in x_draw_glyph_string.) */
+int x_use_underline_position_properties;
+
+/* Non-zero means to draw the underline at the same place as the descent line. */
+
+int x_underline_at_descent_line;
+
extern unsigned int msh_mousewheel;
extern void free_frame_menubar ();
for Far East languages. */
int w32_enable_unicode_output;
+/* Flag to enable Cleartype hack for font metrics. */
+static int cleartype_active;
+
DWORD dwWindowsThreadId = 0;
HANDLE hWindowsThread = NULL;
DWORD dwMainThreadId = 0;
HANDLE hMainThread = NULL;
-#ifndef SIF_ALL
-/* These definitions are new with Windows 95. */
-#define SIF_RANGE 0x0001
-#define SIF_PAGE 0x0002
-#define SIF_POS 0x0004
-#define SIF_DISABLENOSCROLL 0x0008
-#define SIF_TRACKPOS 0x0010
-#define SIF_ALL (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
-
-typedef struct tagSCROLLINFO
-{
- UINT cbSize;
- UINT fMask;
- int nMin;
- int nMax;
- UINT nPage;
- int nPos;
- int nTrackPos;
-} SCROLLINFO, FAR *LPSCROLLINFO;
-typedef SCROLLINFO CONST FAR *LPCSCROLLINFO;
-#endif /* SIF_ALL */
-
-/* Dynamic linking to new proportional scroll bar functions. */
-int (PASCAL *pfnSetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi, BOOL fRedraw);
-BOOL (PASCAL *pfnGetScrollInfo) (HWND hwnd, int fnBar, LPSCROLLINFO lpsi);
-
int vertical_scroll_bar_min_handle;
int vertical_scroll_bar_top_border;
int vertical_scroll_bar_bottom_border;
/* Where the mouse was last time we reported a mouse event. */
static RECT last_mouse_glyph;
+static FRAME_PTR last_mouse_glyph_frame;
static Lisp_Object last_mouse_press_frame;
int w32_num_mouse_buttons;
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 *, HDC));
+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;
struct frame *f = XFRAME (WINDOW_FRAME (w));
RECT r;
HDC hdc;
+ struct face *face;
r.left = x;
r.right = x + 1;
r.bottom = y1;
hdc = get_frame_dc (f);
- w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
+ 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);
}
output_cursor.vpos,
output_cursor.x, output_cursor.y);
- x_draw_vertical_border (w);
-
- draw_window_fringes (w);
+ if (draw_window_fringes (w, 1))
+ x_draw_vertical_border (w);
UNBLOCK_INPUT;
}
int oldVH = row->visible_height;
row->visible_height = p->h;
row->y -= rowY - p->y;
- w32_clip_to_row (w, row, hdc);
+ w32_clip_to_row (w, row, -1, hdc);
row->y = oldY;
row->visible_height = oldVH;
}
else
- w32_clip_to_row (w, row, hdc);
+ w32_clip_to_row (w, row, -1, hdc);
if (p->bx >= 0 && !p->overlay_p)
{
p->bx, p->by, p->nx, p->ny);
}
- if (p->which)
+ if (p->which && p->which < max_fringe_bmp)
{
HBITMAP pixmap = fringe_bmp[p->which];
HDC compat_hdc;
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);
}
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;
/* Function prototypes of this page. */
-static XCharStruct *w32_per_char_metric P_ ((XFontStruct *,
- wchar_t *, int));
+XCharStruct *w32_per_char_metric P_ ((XFontStruct *, wchar_t *, int));
static int w32_encode_char P_ ((int, wchar_t *, struct font_info *, int *));
int real_width;
GetCharWidth (hdc, *char2b, *char2b, &real_width);
#endif
+ if (cleartype_active)
+ {
+ /* Cleartype antialiasing causes characters to overhang
+ by a pixel on each side compared with what GetCharABCWidths
+ reports. */
+ 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
/* As far as I can tell, this is the best way to determine what
}
-static XCharStruct *
+XCharStruct *
w32_per_char_metric (font, char2b, font_type)
XFontStruct *font;
wchar_t *char2b;
}
-
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 *,
else
x = s->x;
- if (s->for_overlaps_p || (s->background_filled_p && s->hl != DRAW_CURSOR))
+ if (s->for_overlaps || (s->background_filled_p && s->hl != DRAW_CURSOR))
SetBkMode (s->hdc, TRANSPARENT);
else
SetBkMode (s->hdc, OPAQUE);
{
/* For overstriking (to simulate bold-face), draw the
characters again shifted to the right by one pixel. */
+ 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)
struct glyph *last_glyph;
RECT clip_rect;
- last_x = window_box_right (s->w, s->area);
- if (s->row->full_width_p
- && !s->w->pseudo_window_p)
- {
- last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
- if (s->area != RIGHT_MARGIN_AREA
- || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
- last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
- }
+ 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));
/* The glyph that may have a right box line. */
last_glyph = (s->cmp || s->img
}
-
/* Draw a relief around the image glyph string S. */
static void
{
/* If `x-stretch-block-cursor' is nil, don't draw a block cursor
as wide as the stretch glyph. */
- int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
+ 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);
/* Draw cursor. */
- x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
+ x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height);
/* Clear rest using the GC of the original non-cursor face. */
- if (width < s->background_width)
+ if (width < background_width)
{
XGCValues *gc = s->face->gc;
- int x = s->x + width, y = s->y;
- int w = s->background_width - width, h = s->height;
+ 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))
{
}
}
else if (!s->background_filled_p)
- x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
- s->height);
+ {
+ int background_width = s->background_width;
+ int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA);
+
+ /* Don't draw into left margin, fringe or scrollbar area
+ except for header line and mode line. */
+ 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;
}
/* If S draws into the background of its successor, draw the
background of the successor first so that S can draw into it.
This makes S->next use XDrawString instead of XDrawImageString. */
- if (s->next && s->right_overhang && !s->for_overlaps_p)
+ if (s->next && s->right_overhang && !s->for_overlaps)
{
xassert (s->next->img == NULL);
x_set_glyph_string_gc (s->next);
/* Draw relief (if any) in advance for char/composition so that the
glyph string can be drawn over it. */
- if (!s->for_overlaps_p
+ if (!s->for_overlaps
&& s->face->box != FACE_NO_BOX
&& (s->first_glyph->type == CHAR_GLYPH
|| s->first_glyph->type == COMPOSITE_GLYPH))
break;
case CHAR_GLYPH:
- if (s->for_overlaps_p)
+ if (s->for_overlaps)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 0);
break;
case COMPOSITE_GLYPH:
- if (s->for_overlaps_p || s->gidx > 0)
+ if (s->for_overlaps || s->gidx > 0)
s->background_filled_p = 1;
else
x_draw_glyph_string_background (s, 1);
abort ();
}
- if (!s->for_overlaps_p)
+ if (!s->for_overlaps)
{
/* Draw underline. */
if (s->face->underline_p
&& (s->font->bdf || !s->font->tm.tmUnderlined))
{
unsigned long h = 1;
- unsigned long dy = s->height - h;
+ unsigned long dy = 0;
- /* TODO: Use font information for positioning and thickness
- of underline. See OUTLINETEXTMETRIC, and xterm.c. */
+ if (x_underline_at_descent_line)
+ dy = s->height - h;
+ else
+ {
+ /* TODO: Use font information for positioning and thickness of
+ underline. See OUTLINETEXTMETRIC, and xterm.c. Note: If
+ you make this work, don't forget to change the doc string of
+ x-use-underline-position-properties below. */
+ 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->width, 1);
+ 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->width, 1);
+ s->y + dy, s->background_width, 1);
}
}
if (s->face->overline_color_defaulted_p)
{
w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x,
- s->y + dy, s->width, h);
+ s->y + dy, s->background_width, h);
}
else
{
- w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x,
- s->y + dy, s->width, h);
+ w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x,
+ s->y + dy, s->background_width, h);
}
}
/* If the dirty region is not what we expected, redraw the entire frame. */
if (!EqualRgn (combined, expect_dirty))
SET_FRAME_GARBAGED (f);
+
+ DeleteObject (dirty);
+ DeleteObject (combined);
}
UNBLOCK_INPUT;
+ DeleteObject (expect_dirty);
}
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);
+}
+/* Handle FocusIn and FocusOut state changes for FRAME.
+ If FRAME has focus and there exists more than one frame, puts
+ a FOCUS_IN_EVENT into *BUFP. */
+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;
+
+ /* Don't stop displaying the initial startup message
+ for a switch-frame event we don't need. */
+ 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;
+ /* TODO: IME focus? */
+ }
+ 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);
+ }
- if (dpyinfo->w32_focus_frame && dpyinfo->w32_focus_frame->auto_raise)
- pending_autoraise_frame = dpyinfo->w32_focus_frame;
- else
- pending_autoraise_frame = 0;
+ /* TODO: IME focus? */
}
+}
- x_frame_rehighlight (dpyinfo);
+
+/* The focus may have changed. Figure out if it is a real focus change,
+ by checking both FocusIn/Out and Enter/LeaveNotify events.
+
+ Returns FOCUS_IN_EVENT event in *BUFP. */
+
+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;
+
+ /* On w32, this is only called from focus events, so no switch needed. */
+ x_focus_changed (event->msg.message,
+ (event->msg.message == WM_KILLFOCUS ?
+ FOCUS_IMPLICIT : FOCUS_EXPLICIT),
+ dpyinfo, frame, bufp);
}
+
/* Handle an event saying the mouse has moved out of an Emacs frame. */
void
result->modifiers = (msg->dwModifiers
| ((delta < 0 ) ? down_modifier : up_modifier));
- p.x = LOWORD (msg->msg.lParam);
- p.y = HIWORD (msg->msg.lParam);
+ /* With multiple monitors, we can legitimately get negative
+ coordinates, so cast to short to interpret them correctly. */
+ 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);
DragFinish (hdrop);
XSETFRAME (frame, f);
- result->frame_or_window = Fcons (frame, files);
- result->arg = Qnil;
+ result->frame_or_window = frame;
+ result->arg = files;
return Qnil;
}
static MSG last_mouse_motion_event;
static Lisp_Object last_mouse_motion_frame;
-static void remember_mouse_glyph P_ ((struct frame *, int, int));
-
-static void
+static int
note_mouse_movement (frame, msg)
FRAME_PTR frame;
MSG *msg;
frame->mouse_moved = 1;
last_mouse_scroll_bar = Qnil;
note_mouse_highlight (frame, -1, -1);
+ last_mouse_glyph_frame = 0;
+ return 1;
}
/* Has the mouse moved off the glyph it was on at the last sighting? */
- else if (mouse_x < last_mouse_glyph.left
- || mouse_x > last_mouse_glyph.right
- || mouse_y < last_mouse_glyph.top
- || mouse_y > last_mouse_glyph.bottom)
+ 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;
gets called when mouse tracking is enabled but we also need
to keep track of the mouse for help_echo and highlighting at
other times. */
- remember_mouse_glyph (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;
}
\f
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 int glyph_rect P_ ((struct frame *f, int, int, RECT *));
-
static void
redo_mouse_highlight ()
{
PostMessage (window, WM_EMACS_SETCURSOR, (WPARAM) cursor, 0);
}
-
-/* Try to determine frame pixel position and size of the glyph under
- frame pixel coordinates X/Y on frame F . Return the position and
- size in *RECT. Value is non-zero if we could compute these
- values. */
-
-static int
-glyph_rect (f, x, y, rect)
- struct frame *f;
- int x, y;
- RECT *rect;
-{
- Lisp_Object window;
-
- window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
-
- if (!NILP (window))
- {
- struct window *w = XWINDOW (window);
- struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
- struct glyph_row *end = r + w->current_matrix->nrows - 1;
-
- for (; r < end && r->enabled_p; ++r)
- if (r->y <= y && r->y + r->height > y)
- {
- /* Found the row at y. */
- struct glyph *g = r->glyphs[TEXT_AREA];
- struct glyph *end = g + r->used[TEXT_AREA];
- int gx;
-
- rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
- rect->bottom = rect->top + r->height;
-
- if (x < r->x)
- {
- /* x is to the left of the first glyph in the row. */
- /* Shouldn't this be a pixel value?
- WINDOW_LEFT_EDGE_X (w) seems to be the right value.
- ++KFS */
- rect->left = WINDOW_LEFT_EDGE_COL (w);
- rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
- return 1;
- }
-
- for (gx = r->x; g < end; gx += g->pixel_width, ++g)
- if (gx <= x && gx + g->pixel_width > x)
- {
- /* x is on a glyph. */
- rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
- rect->right = rect->left + g->pixel_width;
- return 1;
- }
-
- /* x is to the right of the last glyph in the row. */
- rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
- /* Shouldn't this be a pixel value?
- WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
- ++KFS */
- rect->right = WINDOW_RIGHT_EDGE_COL (w);
- return 1;
- }
- }
-
- /* The y is not on any row. */
- return 0;
-}
-
-/* Record the position of the mouse in last_mouse_glyph. */
-static void
-remember_mouse_glyph (f1, gx, gy)
- struct frame * f1;
- int gx, gy;
-{
- if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
- {
- int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
- int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
-
- /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
- round down even for negative values. */
- if (gx < 0)
- gx -= width - 1;
- if (gy < 0)
- gy -= height - 1;
-#if 0
- /* This was the original code from XTmouse_position, but it seems
- to give the position of the glyph diagonally next to the one
- the mouse is over. */
- gx = (gx + width - 1) / width * width;
- gy = (gy + height - 1) / height * height;
-#else
- gx = gx / width * width;
- gy = gy / height * height;
-#endif
-
- last_mouse_glyph.left = gx;
- last_mouse_glyph.top = gy;
- last_mouse_glyph.right = gx + width;
- last_mouse_glyph.bottom = gy + height;
- }
-}
-
/* Return the current position of the mouse.
*fp should be a frame which indicates which display to ask about.
on it, i.e. into the same rectangles that matrices on
the frame are divided into. */
-#if OLD_REDISPLAY_CODE
- int ignore1, ignore2;
-
ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
-
- pixel_to_glyph_coords (f1, pt.x, pt.y, &ignore1, &ignore2,
- &last_mouse_glyph,
- FRAME_W32_DISPLAY_INFO (f1)->grabbed
- || insist);
-#else
- ScreenToClient (FRAME_W32_WINDOW (f1), &pt);
- remember_mouse_glyph (f1, pt.x, pt.y);
-#endif
+ remember_mouse_glyph (f1, pt.x, pt.y, &last_mouse_glyph);
+ last_mouse_glyph_frame = f1;
*bar_window = Qnil;
*part = 0;
double range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
int sb_page, sb_pos;
BOOL draggingp = !NILP (bar->dragging) ? TRUE : FALSE;
+ SCROLLINFO si;
if (whole)
{
BLOCK_INPUT;
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
-
- si.cbSize = sizeof (si);
- /* Only update page size if currently dragging, to reduce
- flicker effects. */
- if (draggingp)
- si.fMask = SIF_PAGE;
- else
- si.fMask = SIF_PAGE | SIF_POS;
- si.nPage = sb_page;
- si.nPos = sb_pos;
-
- pfnSetScrollInfo (w, SB_CTL, &si, !draggingp);
- }
+ si.cbSize = sizeof (si);
+ /* Only update page size if currently dragging, to reduce
+ flicker effects. */
+ if (draggingp)
+ si.fMask = SIF_PAGE;
else
- SetScrollPos (w, SB_CTL, sb_pos, !draggingp);
+ si.fMask = SIF_PAGE | SIF_POS;
+ si.nPage = sb_page;
+ si.nPos = sb_pos;
+
+ SetScrollInfo (w, SB_CTL, &si, !draggingp);
UNBLOCK_INPUT;
}
/*#define ATTACH_THREADS*/
-BOOL
+static BOOL
my_show_window (FRAME_PTR f, HWND hwnd, int how)
{
#ifndef ATTACH_THREADS
#endif
}
-void
+static void
my_set_window_pos (HWND hwnd, HWND hwndAfter,
int x, int y, int cx, int cy, UINT flags)
{
#endif
}
-void
+static void
my_set_focus (f, hwnd)
struct frame * f;
HWND hwnd;
(WPARAM) hwnd, 0);
}
-void
+static void
my_set_foreground_window (hwnd)
HWND hwnd;
{
SendMessage (hwnd, WM_EMACS_SETFOREGROUND, (WPARAM) hwnd, 0);
}
-void
+
+static void
my_destroy_window (f, hwnd)
struct frame * f;
HWND hwnd;
{
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));
hwnd = my_create_scrollbar (f, bar);
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
-
- 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;
+ 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;
- pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
- }
- else
- {
- SetScrollRange (hwnd, SB_CTL, 0,
- VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
- SetScrollPos (hwnd, SB_CTL, 0, FALSE);
- }
+ SetScrollInfo (hwnd, SB_CTL, &si, FALSE);
SET_SCROLL_BAR_W32_WINDOW (bar, hwnd);
else
{
HDC hdc;
+ SCROLLINFO si;
+
BLOCK_INPUT;
if (width && height)
{
MoveWindow (hwnd, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM,
top, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
max (height, 1), TRUE);
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
- 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;
+ 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);
- pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
- }
- else
- SetScrollRange (hwnd, SB_CTL, 0,
- VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
my_show_window (f, hwnd, SW_NORMAL);
/* InvalidateRect (w, NULL, FALSE); */
int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
int y;
int dragging = !NILP (bar->dragging);
+ SCROLLINFO si;
- if (pfnGetScrollInfo)
- {
- SCROLLINFO si;
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
- si.cbSize = sizeof (si);
- si.fMask = SIF_POS;
-
- pfnGetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
- y = si.nPos;
- }
- else
- y = GetScrollPos ((HWND) msg->msg.lParam, SB_CTL);
+ GetScrollInfo ((HWND) msg->msg.lParam, SB_CTL, &si);
+ y = si.nPos;
bar->dragging = Qnil;
emacs_event->part = scroll_bar_handle;
/* "Silently" update current position. */
- if (pfnSetScrollInfo)
- {
- SCROLLINFO si;
+ {
+ SCROLLINFO si;
- si.cbSize = sizeof (si);
- si.fMask = SIF_POS;
- si.nPos = y;
- /* Remember apparent position (we actually lag behind the real
- position, so don't set that directly. */
- last_scroll_bar_drag_pos = y;
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS;
+ si.nPos = y;
+ /* Remember apparent position (we actually lag behind the real
+ position, so don't set that directly. */
+ last_scroll_bar_drag_pos = y;
- pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
- }
- else
- SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, FALSE);
+ SetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, FALSE);
+ }
break;
case SB_ENDSCROLL:
/* If this is the end of a drag sequence, then reset the scroll
nothing. */
if (dragging)
{
- if (pfnSetScrollInfo)
- {
- 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;
- pfnSetScrollInfo (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, &si, TRUE);
- }
- else
- SetScrollPos (SCROLL_BAR_W32_WINDOW (bar), SB_CTL, y, TRUE);
+ 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);
}
/* fall through */
default:
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;
- if (pfnGetScrollInfo)
- {
- SCROLLINFO si;
+ si.cbSize = sizeof (si);
+ si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
- si.cbSize = sizeof (si);
- si.fMask = SIF_POS | SIF_PAGE | SIF_RANGE;
-
- pfnGetScrollInfo (w, SB_CTL, &si);
- pos = si.nPos;
- top_range = si.nMax - si.nPage + 1;
- }
- else
- pos = GetScrollPos (w, SB_CTL);
+ GetScrollInfo (w, SB_CTL, &si);
+ pos = si.nPos;
+ top_range = si.nMax - si.nPage + 1;
switch (LOWORD (last_mouse_scroll_bar_pos))
{
if (f && !f->iconified)
{
- if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+ 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 (f && !f->iconified)
{
- if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
+ 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;
}
previous_help_echo_string = help_echo_string;
+ help_echo_string = Qnil;
if (dpyinfo->grabbed && last_mouse_frame
&& FRAME_LIVE_P (last_mouse_frame))
if (f)
{
/* Generate SELECT_WINDOW_EVENTs when needed. */
- if (mouse_autoselect_window)
+ if (!NILP (Vmouse_autoselect_window))
{
Lisp_Object window;
int x = LOWORD (msg.msg.lParam);
last_window=window;
}
- note_mouse_movement (f, &msg.msg);
+ if (!note_mouse_movement (f, &msg.msg))
+ help_echo_string = previous_help_echo_string;
}
else
{
/* Ignore any mouse motion that happened before this
event; any subsequent mouse-movement Emacs events
should reflect only motion after the
- ButtonPress. */
+ ButtonPress. */
f->mouse_moved = 0;
}
last_mouse_frame = f;
f->async_visible = 1;
f->async_iconified = 0;
- /* wait_reading_process_input will notice this and update
+ /* wait_reading_process_output will notice this and update
the frame's display structures. */
SET_FRAME_GARBAGED (f);
break;
case WM_SETFOCUS:
- /* TODO: Port this change:
- 2002-06-28 Jan D. <jan.h.d@swipnet.se>
- * xterm.h (struct x_output): Add focus_state.
- * xterm.c (x_focus_changed): New function.
- (x_detect_focus_change): New function.
- (XTread_socket): Call x_detect_focus_change for FocusIn/FocusOut
- EnterNotify and LeaveNotify to track X focus changes.
- */
- f = x_any_window_to_frame (dpyinfo, msg.msg.hwnd);
-
- dpyinfo->w32_focus_event_frame = f;
-
- if (f)
- x_new_focus_frame (dpyinfo, f);
-
+ w32_detect_focus_change (dpyinfo, &msg, &inev);
dpyinfo->grabbed = 0;
check_visibility = 1;
break;
case WM_KILLFOCUS:
- /* TODO: some of this belongs in MOUSE_LEAVE */
f = x_top_window_to_frame (dpyinfo, msg.msg.hwnd);
if (f)
}
-
\f
/***********************************************************************
Text Cursor
mode lines must be clipped to the whole window. */
static void
-w32_clip_to_row (w, row, hdc)
+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_y, window_width;
+ int window_x, window_y, window_width;
- window_box (w, -1, 0, &window_y, &window_width, 0);
+ window_box (w, area, &window_x, &window_y, &window_width, 0);
- clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 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;
struct frame *f = XFRAME (WINDOW_FRAME (w));
HDC hdc;
RECT rect;
- int wd, h;
+ int left, top, h;
struct glyph *cursor_glyph;
HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel);
if (cursor_glyph == NULL)
return;
- /* Compute frame-relative coordinates from window-relative
- coordinates. */
- rect.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
- rect.top = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y)
- + row->ascent - w->phys_cursor_ascent);
-
- /* Compute the proper height and ascent of the rectangle, based
- on the actual glyph. Using the full height of the row looks
- bad when there are tall images on that row. */
- h = max (min (FRAME_LINE_HEIGHT (f), row->height),
- cursor_glyph->ascent + cursor_glyph->descent);
- if (h < row->height)
- rect.top += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
- h--;
-
+ /* Compute frame-relative coordinates for phys cursor. */
+ 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;
- /* Compute the width of the rectangle to draw. If on a stretch
- glyph, and `x-stretch-block-cursor' is nil, don't draw a
- rectangle as wide as the glyph, but use a canonical character
- width instead. */
- wd = cursor_glyph->pixel_width; /* TODO: Why off by one compared with X? */
- if (cursor_glyph->type == STRETCH_GLYPH
- && !x_stretch_cursor_p)
- wd = min (FRAME_COLUMN_WIDTH (f), wd);
- w->phys_cursor_width = wd;
-
- rect.right = rect.left + wd;
hdc = get_frame_dc (f);
/* Set clipping, draw the rectangle, and reset clipping again. */
- w32_clip_to_row (w, row, hdc);
+ w32_clip_to_row (w, row, TEXT_AREA, hdc);
FrameRect (hdc, &rect, hb);
DeleteObject (hb);
w32_set_clip_rectangle (hdc, NULL);
hdc = get_frame_dc (f);
- w32_clip_to_row (w, row, hdc);
+ w32_clip_to_row (w, row, TEXT_AREA, hdc);
if (kind == BAR_CURSOR)
{
struct frame *f;
Lisp_Object icon;
{
- HANDLE hicon;
+ HANDLE main_icon;
+ HANDLE small_icon = NULL;
if (FRAME_W32_WINDOW (f) == 0)
return 1;
if (NILP (icon))
- hicon = LoadIcon (hinst, EMACS_CLASS);
+ main_icon = LoadIcon (hinst, EMACS_CLASS);
else if (STRINGP (icon))
- hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
- LR_DEFAULTSIZE | LR_LOADFROMFILE);
+ {
+ /* Load the main icon from the named file. */
+ main_icon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
+ LR_DEFAULTSIZE | LR_LOADFROMFILE);
+ /* Try to load a small icon to go with it. */
+ small_icon = LoadImage (NULL, (LPCSTR) SDATA (icon), IMAGE_ICON,
+ GetSystemMetrics (SM_CXSMICON),
+ GetSystemMetrics (SM_CYSMICON),
+ LR_LOADFROMFILE);
+ }
else if (SYMBOLP (icon))
{
LPCTSTR name;
else
return 1;
- hicon = LoadIcon (NULL, name);
+ main_icon = LoadIcon (NULL, name);
}
else
return 1;
- if (hicon == NULL)
+ if (main_icon == NULL)
return 1;
PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
- (LPARAM) hicon);
+ (LPARAM) main_icon);
+
+ /* If there is a small icon that goes with it, set that too. */
+ if (small_icon)
+ PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_SMALL,
+ (LPARAM) small_icon);
return 0;
}
x_catch_errors (dpy)
x_catch_errors_unwind (old_val)
x_check_errors (dpy, format)
+x_fully_uncatch_errors ()
+x_catching_errors ()
x_had_errors_p (dpy)
x_clear_errors (dpy)
x_uncatch_errors (dpy, count)
FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
FRAME_FONTSET (f) = -1;
- FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
+ 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);
x_calc_absolute_position (f)
struct frame *f;
{
- POINT pt;
int flags = f->size_hint_flags;
- pt.x = pt.y = 0;
-
- /* Find the position of the outside upper-left corner of
- the inner window, with respect to the outer window.
- But do this only if we will need the results. */
- if (f->output_data.w32->parent_desc != FRAME_W32_DISPLAY_INFO (f)->root_window)
- {
- BLOCK_INPUT;
- MapWindowPoints (FRAME_W32_WINDOW (f),
- f->output_data.w32->parent_desc,
- &pt, 1);
- UNBLOCK_INPUT;
- }
+ /* The sum of the widths of the frame's left and right borders, and
+ the sum of the heights of the frame's top and bottom borders (in
+ pixels) drawn by Windows. */
+ unsigned int left_right_borders_width, top_bottom_borders_height;
- {
- RECT rt;
- rt.left = rt.right = rt.top = rt.bottom = 0;
+ /* Try to get the actual values of these two variables. We compute
+ the border width (height) by subtracting the width (height) of
+ the frame's client area from the width (height) of the frame's
+ entire window. */
+ WINDOWPLACEMENT wp = { 0 };
+ RECT client_rect = { 0 };
- BLOCK_INPUT;
- AdjustWindowRect(&rt, f->output_data.w32->dwStyle,
- FRAME_EXTERNAL_MENU_BAR (f));
- UNBLOCK_INPUT;
+ 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);
- pt.x += (rt.right - rt.left);
- pt.y += (rt.bottom - rt.top);
- }
+ top_bottom_borders_height =
+ (wp.rcNormalPosition.bottom - wp.rcNormalPosition.top) -
+ (client_rect.bottom - client_rect.top);
+ }
+ else
+ {
+ /* Use sensible default values. */
+ left_right_borders_width = 8;
+ top_bottom_borders_height = 32;
+ }
- /* Treat negative positions as relative to the leftmost bottommost
+ /* Treat negative positions as relative to the rightmost bottommost
position that fits on the screen. */
if (flags & XNegative)
f->left_pos = (FRAME_W32_DISPLAY_INFO (f)->width
- - 2 * f->border_width - pt.x
- FRAME_PIXEL_WIDTH (f)
- + f->left_pos);
+ + f->left_pos
+ - (left_right_borders_width - 1));
if (flags & YNegative)
f->top_pos = (FRAME_W32_DISPLAY_INFO (f)->height
- - 2 * f->border_width - pt.y
- FRAME_PIXEL_HEIGHT (f)
- + f->top_pos);
- /* The left_pos and top_pos
- are now relative to the top and left screen edges,
- so the flags should correspond. */
+ + f->top_pos
+ - (top_bottom_borders_height - 1));
+
+ /* The left_pos and top_pos are now relative to the top and left
+ screen edges, so the flags should correspond. */
f->size_hint_flags &= ~ (XNegative | YNegative);
}
before the window gets really visible. */
if (! FRAME_ICONIFIED_P (f)
&& ! f->output_data.w32->asked_for_visible)
- x_set_offset (f, f->left_pos, f->top_pos, 0);
+ {
+ RECT workarea_rect;
+ RECT window_rect;
+
+ /* Adjust vertical window position in order to avoid being
+ covered by a task bar placed at the bottom of the desktop. */
+ 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;
\f
/* Set up use of W32. */
-DWORD w32_msg_worker ();
+DWORD WINAPI w32_msg_worker (void * arg);
void
x_flush (struct frame * f)
w32_system_caret_x = 0;
w32_system_caret_y = 0;
+ /* Initialize w32_use_visible_system_caret based on whether a screen
+ reader is in use. */
+ 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;
PeekMessage (&msg, NULL, 0, 0, PM_NOREMOVE);
hWindowsThread = CreateThread (NULL, 0,
- (LPTHREAD_START_ROUTINE) w32_msg_worker,
- 0, 0, &dwWindowsThreadId);
+ w32_msg_worker,
+ 0, 0, &dwWindowsThreadId);
GetMessage (&msg, NULL, WM_EMACS_DONE, WM_EMACS_DONE);
}
AttachThreadInput (dwMainThreadId, dwWindowsThreadId, TRUE);
#endif
- /* Dynamically link to optional system components. */
+ /* Load system settings. */
{
- HANDLE user_lib = LoadLibrary ("user32.dll");
-
-#define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn)
-
- /* New proportional scroll bar functions. */
- LOAD_PROC (SetScrollInfo);
- LOAD_PROC (GetScrollInfo);
-
-#undef LOAD_PROC
-
- FreeLibrary (user_lib);
+ UINT smoothing_type;
+ BOOL smoothing_enabled;
/* If using proportional scroll bars, ensure handle is at least 5 pixels;
otherwise use the fixed height. */
- vertical_scroll_bar_min_handle = (pfnSetScrollInfo != NULL) ? 5 :
- GetSystemMetrics (SM_CYVTHUMB);
+ vertical_scroll_bar_min_handle = 5;
/* For either kind of scroll bar, take account of the arrows; these
effectively form the border of the main scroll bar range. */
vertical_scroll_bar_top_border = vertical_scroll_bar_bottom_border
= GetSystemMetrics (SM_CYVSCROLL);
+
+ /* Constants that are not always defined by the system headers
+ since they only exist on certain versions of Windows. */
+#ifndef SPI_GETFONTSMOOTHING
+#define SPI_GETFONTSMOOTHING 0x4A
+#endif
+#ifndef SPI_GETFONTSMOOTHINGTYPE
+#define SPI_GETFONTSMOOTHINGTYPE 0x0200A
+#endif
+#ifndef FE_FONTSMOOTHINGCLEARTYPE
+#define FE_FONTSMOOTHINGCLEARTYPE 0x2
+#endif
+
+ /* Determine if Cleartype is in use. Used to enable a hack in
+ the char metric calculations which adds extra pixels to
+ compensate for the "sub-pixels" that are not counted by the
+ system APIs. */
+ cleartype_active =
+ SystemParametersInfo (SPI_GETFONTSMOOTHING, 0, &smoothing_enabled, 0)
+ && smoothing_enabled
+ && SystemParametersInfo (SPI_GETFONTSMOOTHINGTYPE, 0, &smoothing_type, 0)
+ && smoothing_type == FE_FONTSMOOTHINGCLEARTYPE;
}
}
When this variable is set, other variables affecting the appearance of
the cursor have no effect. */);
- /* Initialize w32_use_visible_system_caret based on whether a screen
- reader is in use. */
- if (!SystemParametersInfo (SPI_GETSCREENREADER, 0,
- &w32_use_visible_system_caret, 0))
- w32_use_visible_system_caret = 0;
+ w32_use_visible_system_caret = 0;
+
+ /* We don't yet support this, but defining this here avoids whining
+ from cus-start.el and other places, like "M-x set-variable". */
+ DEFVAR_BOOL ("x-use-underline-position-properties",
+ &x_use_underline_position_properties,
+ doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
+nil means ignore them. If you encounter fonts with bogus
+UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
+to 4.1, set this to nil.
+
+NOTE: Not supported on MS-Windows yet. */);
+ x_use_underline_position_properties = 0;
+
+ DEFVAR_BOOL ("x-underline-at-descent-line",
+ &x_underline_at_descent_line,
+ doc: /* *Non-nil means to draw the underline at the same place as the descent line.
+nil means to draw the underline according to the value of the variable
+`x-use-underline-position-properties', which is usually at the baseline
+level. The default value is nil. */);
+ x_underline_at_descent_line = 0;
DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
doc: /* If not nil, Emacs uses toolkit scroll bars. */);