X-Git-Url: http://git.hcoop.net/bpt/emacs.git/blobdiff_plain/2770d5898ced8f331b6e23c0157f37545920f3d2..cb94103f1744a17f140a94ba322a87e612d39d51:/src/w32fns.c diff --git a/src/w32fns.c b/src/w32fns.c index f7e211649e..d260b0d9be 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -1,12 +1,12 @@ /* Graphical user interface functions for the Microsoft W32 API. Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, - 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) +the Free Software Foundation; either version 3, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, @@ -48,10 +48,12 @@ Boston, MA 02110-1301, USA. */ #include "bitmaps/gray.xbm" +#include #include #include #include #include +#include #include #define FILE_NAME_TEXT_FIELD edt1 @@ -297,6 +299,10 @@ extern int w32_use_visible_system_caret; static HWND w32_visible_system_caret_hwnd; +/* From w32menu.c */ +extern HMENU current_popup_menu; +static int menubar_in_use = 0; + /* Error if we are not connected to MS-Windows. */ void @@ -431,20 +437,21 @@ x_real_positions (f, xptr, yptr) POINT pt; RECT rect; - GetClientRect(FRAME_W32_WINDOW(f), &rect); - AdjustWindowRect(&rect, f->output_data.w32->dwStyle, FRAME_EXTERNAL_MENU_BAR(f)); + /* Get the bounds of the WM window. */ + GetWindowRect (FRAME_W32_WINDOW (f), &rect); - pt.x = rect.left; - pt.y = rect.top; + pt.x = 0; + pt.y = 0; - ClientToScreen (FRAME_W32_WINDOW(f), &pt); + /* Convert (0, 0) in the client area to screen co-ordinates. */ + ClientToScreen (FRAME_W32_WINDOW (f), &pt); /* Remember x_pixels_diff and y_pixels_diff. */ f->x_pixels_diff = pt.x - rect.left; f->y_pixels_diff = pt.y - rect.top; - *xptr = pt.x; - *yptr = pt.y; + *xptr = rect.left; + *yptr = rect.top; } @@ -2080,32 +2087,7 @@ w32_createwindow (f) if (!hprevinst) { - Lisp_Object ifa; - w32_init_class (hinst); - - /* Handle the -geometry command line option and the geometry - settings in the registry. They are decoded and put into - initial-frame-alist by w32-win.el:x-handle-geometry. */ - ifa = Fsymbol_value (intern ("initial-frame-alist")); - if (CONSP (ifa)) - { - Lisp_Object lt = Fassq (Qleft, ifa); - Lisp_Object tp = Fassq (Qtop, ifa); - - if (!NILP (lt)) - { - lt = XCDR (lt); - if (INTEGERP (lt)) - left = lt; - } - if (!NILP (tp)) - { - tp = XCDR (tp); - if (INTEGERP (tp)) - top = tp; - } - } } if (f->size_hint_flags & USPosition || f->size_hint_flags & PPosition) @@ -2535,6 +2517,13 @@ w32_msg_pump (deferred_msg * msg_buf) /* Produced by complete_deferred_msg; just ignore. */ break; case WM_EMACS_CREATEWINDOW: + /* Initialize COM for this window. Even though we don't use it, + some third party shell extensions can cause it to be used in + system dialogs, which causes a crash if it is not initialized. + This is a known bug in Windows, which was fixed long ago, but + the patch for XP is not publically available until XP SP3, + and older versions will never be patched. */ + CoInitialize (NULL); w32_createwindow ((struct frame *) msg.wParam); if (!PostThreadMessage (dwMainThreadId, WM_EMACS_DONE, 0, 0)) abort (); @@ -2714,9 +2703,8 @@ cancel_all_deferred_msgs () PostThreadMessage (dwWindowsThreadId, WM_NULL, 0, 0); } -DWORD -w32_msg_worker (dw) - DWORD dw; +DWORD WINAPI +w32_msg_worker (void *arg) { MSG msg; deferred_msg dummy_buf; @@ -3437,11 +3425,14 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) KillTimer (hwnd, menu_free_timer); menu_free_timer = 0; f = x_window_to_frame (dpyinfo, hwnd); - if (!f->output_data.w32->menu_command_in_progress) + /* If a popup menu is active, don't wipe its strings. */ + if (menubar_in_use + && current_popup_menu == NULL) { /* Free memory used by owner-drawn and help-echo strings. */ w32_free_menu_strings (hwnd); f->output_data.w32->menubar_active = 0; + menubar_in_use = 0; } } return 0; @@ -3493,16 +3484,21 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) if (find_deferred_msg (hwnd, msg) != NULL) abort (); + menubar_in_use = 1; + return send_deferred_msg (&msg_buf, hwnd, msg, wParam, lParam); } case WM_EXITMENULOOP: f = x_window_to_frame (dpyinfo, hwnd); - /* If a menu command is not already in progress, check again - after a short delay, since Windows often (always?) sends the - WM_EXITMENULOOP before the corresponding WM_COMMAND message. */ - if (f && !f->output_data.w32->menu_command_in_progress) + /* If a menu is still active, check again after a short delay, + since Windows often (always?) sends the WM_EXITMENULOOP + before the corresponding WM_COMMAND message. + Don't do this if a popup menu is active, since it is only + menubar menus that require cleaning up in this way. + */ + if (f && menubar_in_use && current_popup_menu == NULL) menu_free_timer = SetTimer (hwnd, MENU_FREE_ID, MENU_FREE_DELAY, NULL); goto dflt; @@ -3657,10 +3653,10 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) } goto command; case WM_COMMAND: + menubar_in_use = 0; f = x_window_to_frame (dpyinfo, hwnd); if (f && HIWORD (wParam) == 0) { - f->output_data.w32->menu_command_in_progress = 1; if (menu_free_timer) { KillTimer (hwnd, menu_free_timer); @@ -3674,6 +3670,10 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) my_post_msg (&wmsg, hwnd, msg, wParam, lParam); goto dflt; + case WM_DESTROY: + CoUninitialize (); + return 0; + case WM_CLOSE: wmsg.dwModifiers = w32_get_modifiers (); my_post_msg (&wmsg, hwnd, msg, wParam, lParam); @@ -3732,8 +3732,11 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) However for top/left sizing we will need to fix the X and Y positions as well. */ - lppos->cx -= wdiff; - lppos->cy -= hdiff; + int cx_mintrack = GetSystemMetrics (SM_CXMINTRACK); + int cy_mintrack = GetSystemMetrics (SM_CYMINTRACK); + + lppos->cx = max (lppos->cx - wdiff, cx_mintrack); + lppos->cy = max (lppos->cy - hdiff, cy_mintrack); if (wp.showCmd != SW_SHOWMAXIMIZED && (lppos->flags & SWP_NOMOVE) == 0) @@ -3757,9 +3760,6 @@ w32_wnd_proc (hwnd, msg, wParam, lParam) goto dflt; case WM_GETMINMAXINFO: - /* Hack to correct bug that allows Emacs frames to be resized - below the Minimum Tracking Size. */ - ((LPMINMAXINFO) lParam)->ptMinTrackSize.y++; /* Hack to allow resizing the Emacs frame above the screen size. Note that Windows 9x limits coordinates to 16-bits. */ ((LPMINMAXINFO) lParam)->ptMaxTrackSize.x = 32767; @@ -7512,6 +7512,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, doc: /* Show STRING in a \"tooltip\" window on frame FRAME. A tooltip window is a small window displaying a string. +This is an internal function; Lisp code should call `tooltip-show'. + FRAME nil or omitted means use the selected frame. PARMS is an optional list of frame parameters which can be @@ -7914,9 +7916,9 @@ If ONLY-DIR-P is non-nil, the user can only select directories. */) /* Apparently NT4 crashes if you give it an unexpected size. I'm not sure about Windows 9x, so play it safe. */ if (w32_major_version > 4 && w32_major_version < 95) - file_details->lStructSize = sizeof (new_file_details); + file_details->lStructSize = sizeof (NEWOPENFILENAME); else - file_details->lStructSize = sizeof (file_details); + file_details->lStructSize = sizeof (OPENFILENAME); file_details->hwndOwner = FRAME_W32_WINDOW (f); /* Undocumented Bug in Common File Dialog: @@ -8070,17 +8072,39 @@ DEFUN ("w32-shell-execute", Fw32_shell_execute, Sw32_shell_execute, 2, 4, 0, doc: /* Get Windows to perform OPERATION on DOCUMENT. This is a wrapper around the ShellExecute system function, which invokes the application registered to handle OPERATION for DOCUMENT. -OPERATION is typically \"open\", \"print\" or \"explore\" (but can be -nil for the default action), and DOCUMENT is typically the name of a -document file or URL, but can also be a program executable to run or -a directory to open in the Windows Explorer. - -If DOCUMENT is a program executable, PARAMETERS can be a string -containing command line parameters, but otherwise should be nil. -SHOW-FLAG can be used to control whether the invoked application is hidden -or minimized. If SHOW-FLAG is nil, the application is displayed normally, -otherwise it is an integer representing a ShowWindow flag: +OPERATION is either nil or a string that names a supported operation. +What operations can be used depends on the particular DOCUMENT and its +handler application, but typically it is one of the following common +operations: + + \"open\" - open DOCUMENT, which could be a file, a directory, or an + executable program. If it is an application, that + application is launched in the current buffer's default + directory. Otherwise, the application associated with + DOCUMENT is launched in the buffer's default directory. + \"print\" - print DOCUMENT, which must be a file + \"explore\" - start the Windows Explorer on DOCUMENT + \"edit\" - launch an editor and open DOCUMENT for editing; which + editor is launched depends on the association for the + specified DOCUMENT + \"find\" - initiate search starting from DOCUMENT which must specify + a directory + nil - invoke the default OPERATION, or \"open\" if default is + not defined or unavailable + +DOCUMENT is typically the name of a document file or a URL, but can +also be a program executable to run, or a directory to open in the +Windows Explorer. + +If DOCUMENT is a program executable, the optional arg PARAMETERS can +be a string containing command line parameters that will be passed to +the program; otherwise, PARAMETERS should be nil or unspecified. + +Second optional argument SHOW-FLAG can be used to control how the +application will be displayed when it is invoked. If SHOW-FLAG is nil +or unspceified, the application is displayed normally, otherwise it is +an integer representing a ShowWindow flag: 0 - start hidden 1 - start normally @@ -8353,6 +8377,30 @@ is set to off if the low bit of NEW-STATE is zero, otherwise on. */) } return Qnil; } + +DEFUN ("w32-window-exists-p", Fw32_window_exists_p, Sw32_window_exists_p, + 2, 2, 0, + doc: /* Return non-nil if a window exists with the specified CLASS and NAME. + +This is a direct interface to the Windows API FindWindow function. */) + (class, name) +Lisp_Object class, name; +{ + HWND hnd; + + if (!NILP (class)) + CHECK_STRING (class); + if (!NILP (name)) + CHECK_STRING (name); + + hnd = FindWindow (STRINGP (class) ? ((LPCTSTR) SDATA (class)) : NULL, + STRINGP (name) ? ((LPCTSTR) SDATA (name)) : NULL); + if (!hnd) + return Qnil; + return Qt; +} + + DEFUN ("file-system-info", Ffile_system_info, Sfile_system_info, 1, 1, 0, doc: /* Return storage information about the file system FILENAME is on. @@ -8919,6 +8967,7 @@ versions of Windows) characters. */); staticpro (&Qw32_charset_unicode); Qw32_charset_unicode = intern ("w32-charset-unicode"); + } #endif #if 0 /* TODO: Port to W32 */ @@ -8963,6 +9012,7 @@ versions of Windows) characters. */); defsubr (&Sw32_registered_hot_keys); defsubr (&Sw32_reconstruct_hot_key); defsubr (&Sw32_toggle_lock_key); + defsubr (&Sw32_window_exists_p); defsubr (&Sw32_find_bdf_fonts); defsubr (&Sfile_system_info); @@ -9024,6 +9074,9 @@ void globals_of_w32fns () &w32_ansi_code_page, doc: /* The ANSI code page used by the system. */); w32_ansi_code_page = GetACP (); + + /* MessageBox does not work without this when linked to comctl32.dll 6.0. */ + InitCommonControls (); } #undef abort