]> code.delx.au - gnu-emacs/blobdiff - src/w32fns.c
Fix last set of Nextstep changes.
[gnu-emacs] / src / w32fns.c
index 2fb0311400740f5b3a91b347a573cf433d94faf5..795e7208569109102e4b58746a207c8c2ade5cb3 100644 (file)
@@ -1,6 +1,6 @@
 /* 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, 2007, 2008
+                 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
                  Free Software Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -27,6 +27,7 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <limits.h>
 #include <errno.h>
 #include <math.h>
+#include <setjmp.h>
 
 #include "lisp.h"
 #include "w32term.h"
@@ -156,22 +157,22 @@ Lisp_Object Vx_no_window_manager;
 static unsigned hourglass_timer = 0;
 static HWND hourglass_hwnd = NULL;
 
+#if 0 /* TODO: Mouse cursor customization.  */
 /* The background and shape of the mouse pointer, and shape when not
    over text or in the modeline.  */
-
 Lisp_Object Vx_pointer_shape, Vx_nontext_pointer_shape, Vx_mode_pointer_shape;
 Lisp_Object Vx_hourglass_pointer_shape, Vx_window_horizontal_drag_shape;
 
 /* The shape when over mouse-sensitive text.  */
 
 Lisp_Object Vx_sensitive_text_pointer_shape;
+#endif
 
 #ifndef IDC_HAND
 #define IDC_HAND MAKEINTRESOURCE(32649)
 #endif
 
 /* Color of chars displayed in cursor box.  */
-
 Lisp_Object Vx_cursor_fore_pixel;
 
 /* Nonzero if using Windows.  */
@@ -242,11 +243,19 @@ struct MONITOR_INFO
     DWORD   dwFlags;
 };
 
+/* Reportedly, VS 6 does not have this in its headers.  */
+#if defined(_MSC_VER) && _MSC_VER < 1300
+DECLARE_HANDLE(HMONITOR);
+#endif
+
 typedef BOOL (WINAPI * TrackMouseEvent_Proc)
   (IN OUT LPTRACKMOUSEEVENT lpEventTrack);
 typedef LONG (WINAPI * ImmGetCompositionString_Proc)
   (IN HIMC context, IN DWORD index, OUT LPVOID buffer, IN DWORD bufLen);
 typedef HIMC (WINAPI * ImmGetContext_Proc) (IN HWND window);
+typedef HWND (WINAPI * ImmReleaseContext_Proc) (IN HWND wnd, IN HIMC context);
+typedef HWND (WINAPI * ImmSetCompositionWindow_Proc) (IN HIMC context,
+                                                     IN COMPOSITIONFORM *form);
 typedef HMONITOR (WINAPI * MonitorFromPoint_Proc) (IN POINT pt, IN DWORD flags);
 typedef BOOL (WINAPI * GetMonitorInfo_Proc)
   (IN HMONITOR monitor, OUT struct MONITOR_INFO* info);
@@ -255,6 +264,8 @@ TrackMouseEvent_Proc track_mouse_event_fn = NULL;
 ClipboardSequence_Proc clipboard_sequence_fn = NULL;
 ImmGetCompositionString_Proc get_composition_string_fn = NULL;
 ImmGetContext_Proc get_ime_context_fn = NULL;
+ImmReleaseContext_Proc release_ime_context_fn = NULL;
+ImmSetCompositionWindow_Proc set_ime_composition_window_fn = NULL;
 MonitorFromPoint_Proc monitor_from_point_fn = NULL;
 GetMonitorInfo_Proc get_monitor_info_fn = NULL;
 
@@ -502,53 +513,6 @@ if the entry is new.  */)
   return (oldrgb);
 }
 
-DEFUN ("w32-load-color-file", Fw32_load_color_file,
-       Sw32_load_color_file, 1, 1, 0,
-       doc: /* Create an alist of color entries from an external file.
-Assign this value to `w32-color-map' to replace the existing color map.
-
-The file should define one named RGB color per line like so:
-  R G B   name
-where R,G,B are numbers between 0 and 255 and name is an arbitrary string.  */)
-    (filename)
-    Lisp_Object filename;
-{
-  FILE *fp;
-  Lisp_Object cmap = Qnil;
-  Lisp_Object abspath;
-
-  CHECK_STRING (filename);
-  abspath = Fexpand_file_name (filename, Qnil);
-
-  fp = fopen (SDATA (filename), "rt");
-  if (fp)
-    {
-      char buf[512];
-      int red, green, blue;
-      int num;
-
-      BLOCK_INPUT;
-
-      while (fgets (buf, sizeof (buf), fp) != NULL) {
-       if (sscanf (buf, "%u %u %u %n", &red, &green, &blue, &num) == 3)
-         {
-           char *name = buf + num;
-           num = strlen (name) - 1;
-           if (name[num] == '\n')
-             name[num] = 0;
-           cmap = Fcons (Fcons (build_string (name),
-                                make_number (RGB (red, green, blue))),
-                         cmap);
-         }
-      }
-      fclose (fp);
-
-      UNBLOCK_INPUT;
-    }
-
-  return cmap;
-}
-
 /* The default colors for the w32 color map */
 typedef struct colormap_t
 {
@@ -1431,7 +1395,7 @@ x_set_mouse_color (f, arg, oldval)
        && mask_color == FRAME_BACKGROUND_PIXEL (f))
     f->output_data.w32->mouse_pixel = FRAME_FOREGROUND_PIXEL (f);
 
-#if 0 /* TODO : cursor changes */
+#if 0 /* TODO : Mouse cursor customization.  */
   BLOCK_INPUT;
 
   /* It's not okay to crash if the user selects a screwy cursor.  */
@@ -2883,7 +2847,12 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
             EndPaint (hwnd, &paintStruct);
             leave_crit ();
 
-            my_post_msg (&wmsg, hwnd, msg, wParam, lParam);
+           /* Change the message type to prevent Windows from
+              combining WM_PAINT messages in the Lisp thread's queue,
+              since Windows assumes that each message queue is
+              dedicated to one frame and does not bother checking
+              that hwnd matches before combining them.  */
+            my_post_msg (&wmsg, hwnd, WM_EMACS_PAINT, wParam, lParam);
 
             return 0;
           }
@@ -3195,16 +3164,55 @@ w32_wnd_proc (hwnd, msg, wParam, lParam)
           buffer = alloca(size);
           size = get_composition_string_fn (context, GCS_RESULTSTR,
                                             buffer, size);
+         release_ime_context_fn (hwnd, context);
+
           signal_user_input ();
           for (i = 0; i < size / sizeof (wchar_t); i++)
             {
               my_post_msg (&wmsg, hwnd, WM_UNICHAR, (WPARAM) buffer[i],
                            lParam);
             }
-          /* We output the whole string above, so ignore following ones
-             until we are notified of the end of composition.  */
-          ignore_ime_char = 1;
+          /* Ignore the messages for the rest of the
+            characters in the string that was output above.  */
+          ignore_ime_char = (size / sizeof (wchar_t)) - 1;
         }
+      else
+       ignore_ime_char--;
+
+      break;
+
+    case WM_IME_STARTCOMPOSITION:
+      if (!set_ime_composition_window_fn)
+       goto dflt;
+      else
+       {
+         COMPOSITIONFORM form;
+         HIMC context;
+         struct window *w;
+
+         if (!context)
+           break;
+
+         f = x_window_to_frame (dpyinfo, hwnd);
+         w = XWINDOW (FRAME_SELECTED_WINDOW (f));
+
+         form.dwStyle = CFS_RECT;
+         form.ptCurrentPos.x = w32_system_caret_x;
+         form.ptCurrentPos.y = w32_system_caret_y;
+
+         form.rcArea.left = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, 0);
+         form.rcArea.top = (WINDOW_TOP_EDGE_Y (w)
+                            + WINDOW_HEADER_LINE_HEIGHT (w));
+         form.rcArea.right = (WINDOW_BOX_RIGHT_EDGE_X (w)
+                              - WINDOW_RIGHT_MARGIN_WIDTH (w)
+                              - WINDOW_RIGHT_FRINGE_WIDTH (w));
+         form.rcArea.bottom = (WINDOW_BOTTOM_EDGE_Y (w)
+                               - WINDOW_MODE_LINE_HEIGHT (w));
+
+         context = get_ime_context_fn (hwnd);
+         set_ime_composition_window_fn (context, &form);
+         release_ime_context_fn (hwnd, context);
+       }
       break;
 
     case WM_IME_ENDCOMPOSITION:
@@ -4197,10 +4205,11 @@ unwind_create_frame (frame)
 
       x_free_frame_resources (f);
 
+#if GLYPH_DEBUG
       /* Check that reference counts are indeed correct.  */
       xassert (dpyinfo->reference_count == dpyinfo_refcount);
       xassert (dpyinfo->image_cache->refcount == image_cache_refcount);
-
+#endif
       return Qt;
     }
 
@@ -4405,7 +4414,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
   x_default_parameter (f, parameters, Qborder_width, make_number (2),
                       "borderWidth", "BorderWidth", RES_TYPE_NUMBER);
 
-  /* We recognize either internalBorderWidth or internalBorder 
+  /* We recognize either internalBorderWidth or internalBorder
      (which is what xterm calls it).  */
   if (NILP (Fassq (Qinternal_border_width, parameters)))
     {
@@ -4670,7 +4679,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 {
   struct w32_display_info *dpyinfo = check_x_display_info (display);
 
-  return make_number (dpyinfo->width);
+  return make_number (x_display_pixel_width (dpyinfo));
 }
 
 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
@@ -4684,7 +4693,7 @@ If omitted or nil, that stands for the selected frame's display.  */)
 {
   struct w32_display_info *dpyinfo = check_x_display_info (display);
 
-  return make_number (dpyinfo->height);
+  return make_number (x_display_pixel_height (dpyinfo));
 }
 
 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
@@ -4949,7 +4958,7 @@ x_display_info_for_name (name)
     error ("Cannot connect to server %s", SDATA (name));
 
   w32_in_use = 1;
-  XSETFASTINT (Vwindow_system_version, 3);
+  XSETFASTINT (Vwindow_system_version, w32_major_version);
 
   return dpyinfo;
 }
@@ -4995,7 +5004,7 @@ terminate Emacs if we can't open the connection.  */)
        Fexpand_file_name (build_string ("rgb.txt"),
                           Fsymbol_value (intern ("data-directory")));
 
-    Vw32_color_map = Fw32_load_color_file (color_file);
+    Vw32_color_map = Fx_load_color_file (color_file);
 
     UNGCPRO;
   }
@@ -5040,7 +5049,7 @@ terminate Emacs if we can't open the connection.  */)
 
   w32_in_use = 1;
 
-  XSETFASTINT (Vwindow_system_version, 3);
+  XSETFASTINT (Vwindow_system_version, w32_major_version);
   return Qnil;
 }
 
@@ -5320,9 +5329,18 @@ w32_hide_hourglass ()
     {
       struct frame *f = x_window_to_frame (&one_w32_display_info,
                                           hourglass_hwnd);
+      if (f)
+       f->output_data.w32->hourglass_p = 0;
+      else
+       /* If frame was deleted, restore to selected frame's cursor.  */
+       f = SELECTED_FRAME ();
+
+      if (FRAME_W32_P (f))
+       SetCursor (f->output_data.w32->current_cursor);
+      else
+       /* No cursors on non GUI frames - restore to stock arrow cursor.  */
+       SetCursor (w32_load_cursor (IDC_ARROW));
 
-      f->output_data.w32->hourglass_p = 0;
-      SetCursor (f->output_data.w32->current_cursor);
       hourglass_shown_p = 0;
     }
 }
@@ -5409,6 +5427,10 @@ x_create_tip_frame (dpyinfo, parms, text)
 
   kb = dpyinfo->terminal->kboard;
 
+  /* The calls to x_get_arg remove elements from PARMS, so copy it to
+     avoid destructive changes behind our caller's back.  */
+  parms = Fcopy_alist (parms);
+
   /* Get the name of the frame to use for resource lookup.  */
   name = x_get_arg (dpyinfo, parms, Qname, "name", "Name", RES_TYPE_STRING);
   if (!STRINGP (name)
@@ -5452,7 +5474,7 @@ x_create_tip_frame (dpyinfo, parms, text)
   FRAME_FONTSET (f)  = -1;
   f->icon_name = Qnil;
 
-#if 0 /* GLYPH_DEBUG TODO: image support.  */
+#if GLYPH_DEBUG
   image_cache_refcount = FRAME_IMAGE_CACHE (f)->refcount;
   dpyinfo_refcount = dpyinfo->reference_count;
 #endif /* GLYPH_DEBUG */
@@ -5478,8 +5500,8 @@ x_create_tip_frame (dpyinfo, parms, text)
   f->resx = dpyinfo->resx;
   f->resy = dpyinfo->resy;
 
-  /* Perhaps, we must allow frame parameter, say `font-backend',
-     to specify which font backends to use.  */
+  if (uniscribe_available)
+    register_font_driver (&uniscribe_font_driver, f);
   register_font_driver (&w32font_driver, f);
 
   x_default_parameter (f, parms, Qfont_backend, Qnil,
@@ -5575,14 +5597,20 @@ x_create_tip_frame (dpyinfo, parms, text)
      of the tooltip frame appear in pink.  Prevent this.  */
   {
     Lisp_Object bg = Fframe_parameter (frame, Qbackground_color);
+    Lisp_Object fg = Fframe_parameter (frame, Qforeground_color);
+    Lisp_Object colors = Qnil;
 
     /* Set tip_frame here, so that */
     tip_frame = frame;
     call2 (Qface_set_after_frame_default, frame, Qnil);
 
     if (!EQ (bg, Fframe_parameter (frame, Qbackground_color)))
-      Fmodify_frame_parameters (frame, Fcons (Fcons (Qbackground_color, bg),
-                                             Qnil));
+      colors = Fcons (Fcons (Qbackground_color, bg), colors);
+    if (!EQ (fg, Fframe_parameter (frame, Qforeground_color)))
+      colors = Fcons (Fcons (Qforeground_color, fg), colors);
+
+    if (!NILP (colors))
+      Fmodify_frame_parameters (frame, colors);
   }
 
   f->no_split = 1;
@@ -5639,8 +5667,8 @@ compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
       /* Default min and max values.  */
       min_x = 0;
       min_y = 0;
-      max_x = FRAME_W32_DISPLAY_INFO (f)->width;
-      max_y = FRAME_W32_DISPLAY_INFO (f)->height;
+      max_x = x_display_pixel_width (FRAME_W32_DISPLAY_INFO (f));
+      max_y = x_display_pixel_height (FRAME_W32_DISPLAY_INFO (f));
 
       BLOCK_INPUT;
       GetCursorPos (&pt);
@@ -5979,7 +6007,7 @@ Value is t if tooltip was open, nil otherwise.  */)
 
   if (FRAMEP (frame))
     {
-      Fdelete_frame (frame, Qnil);
+      delete_frame (frame, Qnil);
       deleted = Qt;
     }
 
@@ -6195,7 +6223,7 @@ DEFUN ("system-move-file-to-trash", Fsystem_move_file_to_trash,
   if (!NILP (Ffile_directory_p (filename))
       && NILP (Ffile_symlink_p (filename)))
     {
-      operation = Qdelete_directory;
+      operation = intern ("delete-directory");
       filename = Fdirectory_file_name (filename);
     }
   filename = Fexpand_file_name (filename, Qnil);
@@ -6629,7 +6657,7 @@ The following %-sequences are provided:
       if (system_status.BatteryFlag & 128)
        {
          battery_status = build_string ("N/A");
-         battery_status_symbol = build_string ("");
+         battery_status_symbol = empty_unibyte_string;
        }
       else if (system_status.BatteryFlag & 8)
        {
@@ -6651,12 +6679,12 @@ The following %-sequences are provided:
       else if (system_status.BatteryFlag & 1)
        {
          battery_status = build_string ("high");
-         battery_status_symbol = build_string ("");
+         battery_status_symbol = empty_unibyte_string;
        }
       else
        {
          battery_status = build_string ("medium");
-         battery_status_symbol = build_string ("");
+         battery_status_symbol = empty_unibyte_string;
        }
 
       if (system_status.BatteryLifePercent > 100)
@@ -6910,7 +6938,8 @@ frame_parm_handler w32_frame_parm_handlers[] =
   0, /* x_set_wait_for_wm, */
   x_set_fullscreen,
   x_set_font_backend,
-  x_set_alpha
+  x_set_alpha,
+  0, /* x_set_sticky */
 };
 
 void
@@ -6943,9 +6972,9 @@ syms_of_w32fns ()
 
 
   Fput (Qundefined_color, Qerror_conditions,
-       Fcons (Qundefined_color, Fcons (Qerror, Qnil)));
+       pure_cons (Qundefined_color, pure_cons (Qerror, Qnil)));
   Fput (Qundefined_color, Qerror_message,
-       build_string ("Undefined color"));
+       make_pure_c_string ("Undefined color"));
 
   staticpro (&w32_grabbed_keys);
   w32_grabbed_keys = Qnil;
@@ -7030,7 +7059,7 @@ Set to nil to handle Caps Lock as the `capslock' key.  */);
 The value can be hyper, super, meta, alt, control or shift for the
 respective modifier, or nil to handle Scroll Lock as the `scroll' key.
 Any other value will cause the Scroll Lock key to be ignored.  */);
-  Vw32_scroll_lock_modifier = Qt;
+  Vw32_scroll_lock_modifier = Qnil;
 
   DEFVAR_LISP ("w32-lwindow-modifier",
               &Vw32_lwindow_modifier,
@@ -7114,6 +7143,7 @@ mic-volume-mute, mic-volume-down, mic-volume-up, mic-toggle,
 bass-down, bass-boost, bass-up, treble-down, treble-up  */);
   w32_pass_multimedia_buttons_to_system = 1;
 
+#if 0 /* TODO: Mouse cursor customization.  */
   DEFVAR_LISP ("x-pointer-shape", &Vx_pointer_shape,
               doc: /* The shape of the pointer when over text.
 Changing the value does not affect existing frames
@@ -7143,6 +7173,7 @@ or when you set the mouse color.  */);
 This variable takes effect when you create a new frame
 or when you set the mouse color.  */);
   Vx_window_horizontal_drag_shape = Qnil;
+#endif
 
   DEFVAR_LISP ("x-cursor-fore-pixel", &Vx_cursor_fore_pixel,
               doc: /* A string indicating the foreground color of the cursor box.  */);
@@ -7226,7 +7257,6 @@ only be necessary if the default setting causes problems.  */);
 
   defsubr (&Sw32_define_rgb_color);
   defsubr (&Sw32_default_color_map);
-  defsubr (&Sw32_load_color_file);
   defsubr (&Sw32_send_sys_command);
   defsubr (&Sw32_shell_execute);
   defsubr (&Sw32_register_hot_key);
@@ -7294,6 +7324,10 @@ globals_of_w32fns ()
       GetProcAddress (imm32_lib, "ImmGetCompositionStringW");
     get_ime_context_fn = (ImmGetContext_Proc)
       GetProcAddress (imm32_lib, "ImmGetContext");
+    release_ime_context_fn = (ImmReleaseContext_Proc)
+      GetProcAddress (imm32_lib, "ImmReleaseContext");
+    set_ime_composition_window_fn = (ImmSetCompositionWindow_Proc)
+      GetProcAddress (imm32_lib, "ImmSetCompositionWindow");
   }
   DEFVAR_INT ("w32-ansi-code-page",
              &w32_ansi_code_page,