]> code.delx.au - gnu-emacs/blobdiff - src/w32fns.c
Merge from emacs--rel--22
[gnu-emacs] / src / w32fns.c
index 34cfb0a28821d2516b2a2a9b066279bf1c3a1839..be3570231dcc2745d24094a081d19d9a42f75765 100644 (file)
@@ -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,
@@ -52,6 +52,7 @@ Boston, MA 02110-1301, USA.  */
 #include <shellapi.h>
 #include <ctype.h>
 #include <winspool.h>
+#include <objbase.h>
 
 #include <dlgs.h>
 #define FILE_NAME_TEXT_FIELD edt1
@@ -297,6 +298,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;
+
 \f
 /* Error if we are not connected to MS-Windows.  */
 void
@@ -431,20 +436,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;
 }
 
 \f
@@ -2510,6 +2516,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 ();
@@ -3411,11 +3424,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;
@@ -3467,16 +3483,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;
 
@@ -3631,10 +3652,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);
@@ -3648,6 +3669,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);
@@ -7486,6 +7511,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
@@ -7888,9 +7915,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: