X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/e597eb7d6c2ce218faa1e060b4e0402cb0bd16a6..9d74382f6f75aafbd7eab700107bb1e31f640c8a:/src/w32term.c diff --git a/src/w32term.c b/src/w32term.c index 71125fe419..2b5c9da39b 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -1,6 +1,6 @@ /* 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. @@ -16,8 +16,8 @@ GNU General Public License for more details. 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 #include @@ -62,7 +62,8 @@ Boston, MA 02111-1307, USA. */ /* 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. */ @@ -86,6 +87,10 @@ static int any_help_event_p; /* 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; + extern unsigned int msh_mousewheel; extern void free_frame_menubar (); @@ -133,6 +138,9 @@ int w32_use_visible_system_caret; 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; @@ -175,6 +183,7 @@ int last_scroll_bar_drag_pos; /* 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; @@ -254,12 +263,21 @@ 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 *, 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; @@ -498,6 +516,7 @@ w32_draw_vertical_window_border (w, x, y0, y1) struct frame *f = XFRAME (WINDOW_FRAME (w)); RECT r; HDC hdc; + struct face *face; r.left = x; r.right = x + 1; @@ -505,7 +524,12 @@ w32_draw_vertical_window_border (w, x, y0, y1) 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); } @@ -539,9 +563,8 @@ x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p) 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; } @@ -691,12 +714,12 @@ w32_draw_fringe_bitmap (w, row, p) 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) { @@ -704,7 +727,7 @@ w32_draw_fringe_bitmap (w, row, 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; @@ -767,6 +790,15 @@ w32_define_fringe_bitmap (which, bits, h, wd) 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); } @@ -774,6 +806,9 @@ 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; @@ -807,8 +842,7 @@ w32_reset_terminal_modes (void) /* 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 *)); @@ -888,6 +922,16 @@ w32_native_per_char_metric (font, char2b, font_type, pcm) 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 @@ -945,7 +989,7 @@ w32_native_per_char_metric (font, char2b, font_type, pcm) } -static XCharStruct * +XCharStruct * w32_per_char_metric (font, char2b, font_type) XFontStruct *font; wchar_t *char2b; @@ -1197,7 +1241,6 @@ w32_text_out (s, x, y,chars,nchars) } - 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 *, @@ -1525,7 +1568,7 @@ x_draw_glyph_string_foreground (s) 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); @@ -1911,15 +1954,9 @@ x_draw_glyph_string_box (s) 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 @@ -2049,7 +2086,6 @@ x_draw_image_foreground (s) } - /* Draw a relief around the image glyph string S. */ static void @@ -2413,7 +2449,7 @@ x_draw_glyph_string (s) /* 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); @@ -2426,7 +2462,7 @@ x_draw_glyph_string (s) /* 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)) @@ -2452,7 +2488,7 @@ x_draw_glyph_string (s) 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); @@ -2460,7 +2496,7 @@ x_draw_glyph_string (s) 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); @@ -2471,7 +2507,7 @@ x_draw_glyph_string (s) abort (); } - if (!s->for_overlaps_p) + if (!s->for_overlaps) { /* Draw underline. */ if (s->face->underline_p @@ -2481,7 +2517,9 @@ x_draw_glyph_string (s) unsigned long dy = s->height - h; /* TODO: Use font information for positioning and thickness - of underline. See OUTLINETEXTMETRIC, and xterm.c. */ + 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. */ if (s->face->underline_defaulted_p) { w32_fill_area (s->f, s->hdc, s->gc->foreground, s->x, @@ -2506,7 +2544,7 @@ x_draw_glyph_string (s) } else { - w32_fill_area (s->f, s->hdc, s->face->underline_color, s->x, + w32_fill_area (s->f, s->hdc, s->face->overline_color, s->x, s->y + dy, s->width, h); } } @@ -2753,9 +2791,13 @@ x_scroll_run (w, run) /* 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); } @@ -2800,23 +2842,90 @@ x_new_focus_frame (dpyinfo, 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); +} +/* 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 @@ -3022,8 +3131,10 @@ construct_mouse_wheel (result, msg, f) 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); @@ -3079,8 +3190,8 @@ construct_drag_n_drop (result, msg, f) 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; } @@ -3096,9 +3207,7 @@ construct_drag_n_drop (result, msg, f) 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; @@ -3115,13 +3224,16 @@ note_mouse_movement (frame, 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; @@ -3130,8 +3242,12 @@ note_mouse_movement (frame, msg) 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; } @@ -3142,8 +3258,6 @@ note_mouse_movement (frame, msg) 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 () @@ -3162,108 +3276,6 @@ w32_define_cursor (window, cursor) { 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. @@ -3355,19 +3367,9 @@ w32_mouse_position (fp, insist, bar_window, part, x, y, time) 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; @@ -3529,7 +3531,7 @@ my_create_scrollbar (f, bar) /*#define ATTACH_THREADS*/ -BOOL +static BOOL my_show_window (FRAME_PTR f, HWND hwnd, int how) { #ifndef ATTACH_THREADS @@ -3540,7 +3542,7 @@ my_show_window (FRAME_PTR f, HWND hwnd, int how) #endif } -void +static void my_set_window_pos (HWND hwnd, HWND hwndAfter, int x, int y, int cx, int cy, UINT flags) { @@ -3558,7 +3560,7 @@ my_set_window_pos (HWND hwnd, HWND hwndAfter, #endif } -void +static void my_set_focus (f, hwnd) struct frame * f; HWND hwnd; @@ -3567,14 +3569,15 @@ my_set_focus (f, 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; @@ -4259,7 +4262,8 @@ w32_read_socket (sd, expected, hold_quit) 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; @@ -4282,7 +4286,8 @@ w32_read_socket (sd, expected, hold_quit) 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; @@ -4311,6 +4316,7 @@ w32_read_socket (sd, expected, hold_quit) } previous_help_echo_string = help_echo_string; + help_echo_string = Qnil; if (dpyinfo->grabbed && last_mouse_frame && FRAME_LIVE_P (last_mouse_frame)) @@ -4349,7 +4355,8 @@ w32_read_socket (sd, expected, hold_quit) last_window=window; } - note_mouse_movement (f, &msg.msg); + if (!note_mouse_movement (f, &msg.msg)) + help_echo_string = previous_help_echo_string; } else { @@ -4570,7 +4577,7 @@ w32_read_socket (sd, expected, hold_quit) 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); @@ -4661,28 +4668,13 @@ w32_read_socket (sd, expected, hold_quit) break; case WM_SETFOCUS: - /* TODO: Port this change: - 2002-06-28 Jan D. - * 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) @@ -4894,7 +4886,6 @@ w32_read_socket (sd, expected, hold_quit) } - /*********************************************************************** Text Cursor @@ -4908,18 +4899,19 @@ w32_read_socket (sd, expected, hold_quit) 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; @@ -4939,7 +4931,7 @@ x_draw_hollow_cursor (w, row) struct frame *f = XFRAME (WINDOW_FRAME (w)); HDC hdc; RECT rect; - int wd, h; + int h; struct glyph *cursor_glyph; HBRUSH hb = CreateSolidBrush (f->output_data.w32->cursor_pixel); @@ -4949,37 +4941,15 @@ x_draw_hollow_cursor (w, row) if (cursor_glyph == NULL) return; - /* Compute frame-relative coordinates from window-relative - coordinates. */ + /* Compute frame-relative coordinates for phys cursor. */ 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--; - + rect.top = get_phys_cursor_geometry (w, row, cursor_glyph, &h); 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); @@ -5045,7 +5015,7 @@ x_draw_bar_cursor (w, row, width, kind) 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) { @@ -5195,16 +5165,25 @@ x_bitmap_icon (f, icon) 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; @@ -5224,16 +5203,21 @@ x_bitmap_icon (f, icon) 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; } @@ -5250,6 +5234,8 @@ x_error_catcher (display, error) 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) @@ -5285,7 +5271,8 @@ x_new_font (f, fontname) 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); @@ -5369,47 +5356,17 @@ void 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; - } - - { - RECT rt; - rt.left = rt.right = rt.top = rt.bottom = 0; - - BLOCK_INPUT; - AdjustWindowRect(&rt, f->output_data.w32->dwStyle, - FRAME_EXTERNAL_MENU_BAR (f)); - UNBLOCK_INPUT; - - pt.x += (rt.right - rt.left); - pt.y += (rt.bottom - rt.top); - } - /* Treat negative positions as relative to the leftmost 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); 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 @@ -6385,6 +6342,12 @@ w32_initialize () 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; @@ -6429,6 +6392,8 @@ w32_initialize () /* Dynamically link to optional system components. */ { HANDLE user_lib = LoadLibrary ("user32.dll"); + UINT smoothing_type; + BOOL smoothing_enabled; #define LOAD_PROC(fn) pfn##fn = (void *) GetProcAddress (user_lib, #fn) @@ -6449,6 +6414,28 @@ w32_initialize () 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; } } @@ -6518,11 +6505,19 @@ software is running as it starts up. 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_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, doc: /* If not nil, Emacs uses toolkit scroll bars. */);