X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/a0a7e8c6de361d15703e78a1e934d0347475dcb8..b336ee388ed5300440e7bab24bf9eec9f250911a:/src/w32term.c diff --git a/src/w32term.c b/src/w32term.c index 403cec7db7..d7c9bc8c15 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 @@ -87,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 (); @@ -134,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; @@ -176,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; @@ -265,6 +273,11 @@ 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; @@ -503,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; @@ -510,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); } @@ -903,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 @@ -1539,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); @@ -2420,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); @@ -2433,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)) @@ -2459,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); @@ -2467,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); @@ -2478,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 @@ -2488,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, @@ -3157,8 +3188,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; } @@ -3174,9 +3205,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; @@ -3193,13 +3222,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; @@ -3208,8 +3240,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; } @@ -3220,8 +3256,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 () @@ -3240,108 +3274,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. @@ -3433,19 +3365,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; @@ -3607,7 +3529,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 @@ -3618,7 +3540,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) { @@ -3636,7 +3558,7 @@ my_set_window_pos (HWND hwnd, HWND hwndAfter, #endif } -void +static void my_set_focus (f, hwnd) struct frame * f; HWND hwnd; @@ -3645,14 +3567,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; @@ -4389,6 +4312,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)) @@ -4427,7 +4351,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 { @@ -5236,16 +5161,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; @@ -5265,16 +5199,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; } @@ -5291,6 +5230,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) @@ -6398,6 +6339,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; @@ -6442,6 +6389,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) @@ -6462,6 +6411,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; } } @@ -6531,11 +6502,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. */);