use dynwind_begin and dynwind_end
[bpt/emacs.git] / src / nsfns.m
index 1e07599..a0fbcfd 100644 (file)
@@ -1,6 +1,6 @@
 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
 
-Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2013 Free Software
+Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2014 Free Software
 Foundation, Inc.
 
 This file is part of GNU Emacs.
@@ -46,6 +46,9 @@ GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
 
 #ifdef NS_IMPL_COCOA
 #include <IOKit/graphics/IOGraphicsLib.h>
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+#include "macfont.h"
+#endif
 #endif
 
 #if 0
@@ -89,9 +92,6 @@ extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
 Lisp_Object Qbuffered;
 Lisp_Object Qfontsize;
 
-/* hack for OS X file panels */
-char panelOK = 0;
-
 EmacsTooltip *ns_tooltip = nil;
 
 /* Need forward declaration here to preserve organizational integrity of file */
@@ -127,7 +127,7 @@ check_ns_display_info (Lisp_Object object)
       struct frame *sf = XFRAME (selected_frame);
 
       if (FRAME_NS_P (sf) && FRAME_LIVE_P (sf))
-       dpyinfo = FRAME_NS_DISPLAY_INFO (sf);
+       dpyinfo = FRAME_DISPLAY_INFO (sf);
       else if (x_display_list != 0)
        dpyinfo = x_display_list;
       else
@@ -146,8 +146,8 @@ check_ns_display_info (Lisp_Object object)
     dpyinfo = ns_display_info_for_name (object);
   else
     {
-      FRAME_PTR f = decode_window_system_frame (object);
-      dpyinfo = FRAME_NS_DISPLAY_INFO (f);
+      struct frame *f = decode_window_system_frame (object);
+      dpyinfo = FRAME_DISPLAY_INFO (f);
     }
 
   return dpyinfo;
@@ -175,28 +175,21 @@ ns_get_window (Lisp_Object maybeFrame)
 struct ns_display_info *
 ns_display_info_for_name (Lisp_Object name)
 {
-  Lisp_Object names;
   struct ns_display_info *dpyinfo;
 
   CHECK_STRING (name);
 
-  for (dpyinfo = x_display_list, names = ns_display_name_list;
-       dpyinfo;
-       dpyinfo = dpyinfo->next, names = XCDR (names))
-    {
-      Lisp_Object tem;
-      tem = Fstring_equal (XCAR (XCAR (names)), name);
-      if (!NILP (tem))
-        return dpyinfo;
-    }
+  for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
+    if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
+      return dpyinfo;
 
-  error ("Emacs for OpenStep does not yet support multi-display.");
+  error ("Emacs for Nextstep does not yet support multi-display");
 
   Fx_open_connection (name, Qnil, Qnil);
   dpyinfo = x_display_list;
 
   if (dpyinfo == 0)
-    error ("OpenStep on %s not responding.\n", SDATA (name));
+    error ("Display on %s not responding.\n", SDATA (name));
 
   return dpyinfo;
 }
@@ -410,23 +403,23 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
       if (!NILP (f->title))
         arg = f->title;
       else
-        /* explicit name and no icon-name -> explicit_name */
+        /* Explicit name and no icon-name -> explicit_name.  */
         if (f->explicit_name)
           arg = f->name;
         else
           {
-            /* no explicit name and no icon-name ->
-               name has to be rebuild from icon_title_format */
-            windows_or_buffers_changed++;
+            /* No explicit name and no icon-name ->
+               name has to be rebuild from icon_title_format */
+            windows_or_buffers_changed = 62;
             return;
           }
     }
 
   /* Don't change the name if it's already NAME.  */
-  if ([[view window] miniwindowTitle] &&
-      ([[[view window] miniwindowTitle]
+  if ([[view window] miniwindowTitle]
+      && ([[[view window] miniwindowTitle]
              isEqualToString: [NSString stringWithUTF8String:
-                                           SSDATA (arg)]]))
+                                         SSDATA (arg)]]))
     return;
 
   [[view window] setMiniwindowTitle:
@@ -434,7 +427,7 @@ x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 }
 
 static void
-ns_set_name_internal (FRAME_PTR f, Lisp_Object name)
+ns_set_name_internal (struct frame *f, Lisp_Object name)
 {
   struct gcpro gcpro1;
   Lisp_Object encoded_name, encoded_icon_name;
@@ -458,8 +451,8 @@ ns_set_name_internal (FRAME_PTR f, Lisp_Object name)
 
   str = [NSString stringWithUTF8String: SSDATA (encoded_icon_name)];
 
-  if ([[view window] miniwindowTitle] &&
-      ! [[[view window] miniwindowTitle] isEqualToString: str])
+  if ([[view window] miniwindowTitle]
+      && ! [[[view window] miniwindowTitle] isEqualToString: str])
     [[view window] setMiniwindowTitle: str];
 
 }
@@ -476,7 +469,7 @@ ns_set_name (struct frame *f, Lisp_Object name, int explicit)
       /* If we're switching from explicit to implicit, we had better
          update the mode lines and thereby update the title.  */
       if (f->explicit_name && NILP (name))
-        update_mode_lines = 1;
+        update_mode_lines = 21;
 
       f->explicit_name = ! NILP (name);
     }
@@ -484,7 +477,7 @@ ns_set_name (struct frame *f, Lisp_Object name, int explicit)
     return;
 
   if (NILP (name))
-    name = build_string([ns_app_name UTF8String]);
+    name = build_string ([ns_app_name UTF8String]);
   else
     CHECK_STRING (name);
 
@@ -494,7 +487,7 @@ ns_set_name (struct frame *f, Lisp_Object name, int explicit)
 
   fset_name (f, name);
 
-  /* title overrides explicit name */
+  /* Title overrides explicit name.  */
   if (! NILP (f->title))
     name = f->title;
 
@@ -506,7 +499,7 @@ ns_set_name (struct frame *f, Lisp_Object name, int explicit)
    specified a name for the frame; the name will override any set by the
    redisplay code.  */
 static void
-x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   NSTRACE (x_explicitly_set_name);
   ns_set_name (f, arg, 1);
@@ -517,7 +510,7 @@ x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
    name; names set this way will never override names set by the user's
    lisp code.  */
 void
-x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   NSTRACE (x_implicitly_set_name);
 
@@ -541,7 +534,7 @@ x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
   if (EQ (name, f->title))
     return;
 
-  update_mode_lines = 1;
+  update_mode_lines = 22;
 
   fset_title (f, name);
 
@@ -710,7 +703,7 @@ x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
         }
     }
 
-  x_set_window_size (f, 0, f->text_cols, f->text_lines);
+  x_set_window_size (f, 0, f->text_cols, f->text_lines, 0);
 }
 
 
@@ -830,9 +823,9 @@ int
 ns_lisp_to_cursor_type (Lisp_Object arg)
 {
   char *str;
-  if (XTYPE (arg) == Lisp_String)
+  if (STRINGP (arg))
     str = SSDATA (arg);
-  else if (XTYPE (arg) == Lisp_Symbol)
+  else if (SYMBOLP (arg))
     str = SSDATA (SYMBOL_NAME (arg));
   else return -1;
   if (!strcmp (str, "box"))    return FILLED_BOX_CURSOR;
@@ -860,14 +853,10 @@ ns_cursor_type_to_lisp (int arg)
 
 /* This is the same as the xfns.c definition.  */
 static void
-x_set_cursor_type (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
+x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 {
   set_frame_cursor_types (f, arg);
-
-  /* Make sure the cursor gets redrawn.  */
-  cursor_type_changed = 1;
 }
-\f
 
 /* called to set mouse pointer color, but all other terms use it to
    initialize pointer types (and don't set the color ;) */
@@ -884,12 +873,16 @@ x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
 static Lisp_Object
 ns_appkit_version_str (void)
 {
-  char tmp[80];
+  char tmp[256];
 
 #ifdef NS_IMPL_GNUSTEP
   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
-#elif defined(NS_IMPL_COCOA)
-  sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber);
+#elif defined (NS_IMPL_COCOA)
+  NSString *osversion
+    = [[NSProcessInfo processInfo] operatingSystemVersionString];
+  sprintf(tmp, "appkit-%.2f %s",
+          NSAppKitVersionNumber,
+          [osversion UTF8String]);
 #else
   tmp = "ns-unknown";
 #endif
@@ -905,7 +898,7 @@ ns_appkit_version_int (void)
 {
 #ifdef NS_IMPL_GNUSTEP
   return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
-#elif defined(NS_IMPL_COCOA)
+#elif defined (NS_IMPL_COCOA)
   return (int)NSAppKitVersionNumber;
 #endif
   return 0;
@@ -957,6 +950,8 @@ frame_parm_handler ns_frame_parm_handlers[] =
   x_set_icon_name,
   x_set_icon_type,
   x_set_internal_border_width, /* generic OK */
+  0, /* x_set_right_divider_width */
+  0, /* x_set_bottom_divider_width */
   x_set_menu_bar_lines,
   x_set_mouse_color,
   x_explicitly_set_name,
@@ -984,7 +979,7 @@ frame_parm_handler ns_frame_parm_handlers[] =
 /* Handler for signals raised during x_create_frame.
    FRAME is the frame which is partially constructed.  */
 
-static Lisp_Object
+static void
 unwind_create_frame (Lisp_Object frame)
 {
   struct frame *f = XFRAME (frame);
@@ -993,13 +988,13 @@ unwind_create_frame (Lisp_Object frame)
      display is disconnected after the frame has become official, but
      before x_create_frame removes the unwind protect.  */
   if (!FRAME_LIVE_P (f))
-    return Qnil;
+    return;
 
   /* If frame is ``official'', nothing to do.  */
   if (NILP (Fmemq (frame, Vframe_list)))
     {
 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
-      struct ns_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
+      struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 #endif
 
       x_free_frame_resources (f);
@@ -1009,10 +1004,7 @@ unwind_create_frame (Lisp_Object frame)
       /* Check that reference counts are indeed correct.  */
       eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
 #endif
-      return Qt;
     }
-
-  return Qnil;
 }
 
 /*
@@ -1036,7 +1028,7 @@ get_geometry_from_preferences (struct ns_display_info *dpyinfo,
   };
 
   int i;
-  for (i = 0; i < sizeof (r)/sizeof (r[0]); ++i)
+  for (i = 0; i < ARRAYELTS (r); ++i)
     {
       if (NILP (Fassq (r[i].tem, parms)))
         {
@@ -1074,9 +1066,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   Lisp_Object frame, tem;
   Lisp_Object name;
   int minibuffer_only = 0;
-  int window_prompting = 0;
+  long window_prompting = 0;
   int width, height;
-  ptrdiff_t count = specpdl_ptr - specpdl;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
   Lisp_Object display;
   struct ns_display_info *dpyinfo = NULL;
@@ -1149,9 +1140,11 @@ This function is an internal primitive--use `make-frame' instead.  */)
   if (! STRINGP (f->icon_name))
     fset_icon_name (f, Qnil);
 
-  FRAME_NS_DISPLAY_INFO (f) = dpyinfo;
+  FRAME_DISPLAY_INFO (f) = dpyinfo;
 
-  /* With FRAME_NS_DISPLAY_INFO set up, this unwind-protect is safe.  */
+  dynwind_begin ();
+
+  /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
   record_unwind_protect (unwind_create_frame, frame);
 
   f->output_data.ns->window_desc = desc_ctr++;
@@ -1162,7 +1155,7 @@ This function is an internal primitive--use `make-frame' instead.  */)
     }
   else
     {
-      f->output_data.ns->parent_desc = FRAME_NS_DISPLAY_INFO (f)->root_window;
+      f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
       f->output_data.ns->explicit_parent = 0;
     }
 
@@ -1181,7 +1174,16 @@ This function is an internal primitive--use `make-frame' instead.  */)
     }
 
   block_input ();
+
+#ifdef NS_IMPL_COCOA
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+  if (CTGetCoreTextVersion != NULL
+      && CTGetCoreTextVersion () >= kCTVersionNumber10_5)
+    mac_register_font_driver (f);
+#endif
+#endif
   register_font_driver (&nsfont_driver, f);
+
   x_default_parameter (f, parms, Qfont_backend, Qnil,
                        "fontBackend", "FontBackend", RES_TYPE_STRING);
 
@@ -1191,9 +1193,15 @@ This function is an internal primitive--use `make-frame' instead.  */)
     x_default_parameter (f, parms, Qfontsize,
                                     make_number (0 /*(int)[font pointSize]*/),
                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
+    // Remove ' Regular', not handled by backends.
+    char *fontname = xstrdup ([[font displayName] UTF8String]);
+    int len = strlen (fontname);
+    if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0)
+      fontname[len-8] = '\0';
     x_default_parameter (f, parms, Qfont,
-                                 build_string ([[font fontName] UTF8String]),
+                                 build_string (fontname),
                                  "font", "Font", RES_TYPE_STRING);
+    xfree (fontname);
   }
   unblock_input ();
 
@@ -1234,6 +1242,13 @@ This function is an internal primitive--use `make-frame' instead.  */)
 
   init_frame_faces (f);
 
+  /* Read comment about this code in corresponding place in xfns.c.  */
+  width = FRAME_TEXT_WIDTH (f);
+  height = FRAME_TEXT_HEIGHT (f);
+  FRAME_TEXT_HEIGHT (f) = 0;
+  SET_FRAME_WIDTH (f, 0);
+  change_frame_size (f, width, height, 1, 0, 0, 1);
+
   /* The resources controlling the menu-bar and tool-bar are
      processed specially at startup, and reflected in the mode
      variables; ignore them here.  */
@@ -1265,7 +1280,8 @@ This function is an internal primitive--use `make-frame' instead.  */)
   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
-  FRAME_NS_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
+  f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
+  FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
      = [NSCursor arrowCursor];
   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
 
@@ -1297,12 +1313,11 @@ This function is an internal primitive--use `make-frame' instead.  */)
   x_default_parameter (f, parms, Qfullscreen, Qnil,
                        "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
 
-  width = FRAME_COLS (f);
-  height = FRAME_LINES (f);
-
-  SET_FRAME_COLS (f, 0);
-  FRAME_LINES (f) = 0;
-  change_frame_size (f, height, width, 1, 0, 0);
+  width = FRAME_TEXT_WIDTH (f);
+  height = FRAME_TEXT_HEIGHT (f);
+  FRAME_TEXT_HEIGHT (f) = 0;
+  SET_FRAME_WIDTH (f, 0);
+  change_frame_size (f, width, height, 1, 0, 0, 1);
 
   if (! f->output_data.ns->explicit_parent)
     {
@@ -1346,17 +1361,14 @@ This function is an internal primitive--use `make-frame' instead.  */)
      and similar functions.  */
   Vwindow_list = Qnil;
 
-  return unbind_to (count, frame);
+  dynwind_end ();
+  return frame;
 }
 
-
-DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
-       doc: /* Set the input focus to FRAME.
-FRAME nil means use the selected frame.  */)
-     (Lisp_Object frame)
+void
+x_focus_frame (struct frame *f)
 {
-  struct frame *f = decode_window_system_frame (frame);
-  struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
+  struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
 
   if (dpyinfo->x_focus_frame != f)
     {
@@ -1366,8 +1378,6 @@ FRAME nil means use the selected frame.  */)
       [[view window] makeKeyAndOrderFront: view];
       unblock_input ();
     }
-
-  return Qnil;
 }
 
 
@@ -1378,9 +1388,15 @@ DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
 {
   struct frame *f = decode_window_system_frame (frame);
   id fm = [NSFontManager sharedFontManager];
-
-  [fm setSelectedFont: ((struct nsfont_info *)f->output_data.ns->font)->nsfont
-           isMultiple: NO];
+  struct font *font = f->output_data.ns->font;
+  NSFont *nsfont;
+  if (EQ (font->driver->type, Qns))
+    nsfont = ((struct nsfont_info *)font)->nsfont;
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
+  else
+    nsfont = (NSFont *) macfont_get_nsctfont (font);
+#endif
+  [fm setSelectedFont: nsfont isMultiple: NO];
   [fm orderFrontFontPanel: NSApp];
   return Qnil;
 }
@@ -1396,6 +1412,41 @@ DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
   return Qnil;
 }
 
+static struct
+{
+  id panel;
+  BOOL ret;
+#if ! defined (NS_IMPL_COCOA) || \
+  MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
+  NSString *dirS, *initS;
+  BOOL no_types;
+#endif
+} ns_fd_data;
+
+void
+ns_run_file_dialog (void)
+{
+  if (ns_fd_data.panel == nil) return;
+#if defined (NS_IMPL_COCOA) && \
+  MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+  ns_fd_data.ret = [ns_fd_data.panel runModal];
+#else
+  if (ns_fd_data.no_types)
+    {
+      ns_fd_data.ret = [ns_fd_data.panel
+                           runModalForDirectory: ns_fd_data.dirS
+                           file: ns_fd_data.initS];
+    }
+  else
+    {
+      ns_fd_data.ret = [ns_fd_data.panel
+                           runModalForDirectory: ns_fd_data.dirS
+                           file: ns_fd_data.initS
+                           types: nil];
+    }
+#endif
+  ns_fd_data.panel = nil;
+}
 
 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
@@ -1420,6 +1471,7 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
     [NSString stringWithUTF8String: SSDATA (dir)];
   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
     [NSString stringWithUTF8String: SSDATA (init)];
+  NSEvent *nxev;
 
   check_window_system (NULL);
 
@@ -1440,7 +1492,6 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
   [panel setTreatsFilePackagesAsDirectories: YES];
   [panel setDelegate: fileDelegate];
 
-  panelOK = 0;
   if (! NILP (dir_only_p))
     {
       [panel setCanChooseDirectories: YES];
@@ -1454,7 +1505,9 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
       [panel setCanChooseFiles: YES];
     }
 
- block_input ();
+  block_input ();
+  ns_fd_data.panel = panel;
+  ns_fd_data.ret = NO;
 #if defined (NS_IMPL_COCOA) && \
   MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
   if (! NILP (mustmatch) || ! NILP (dir_only_p))
@@ -1465,19 +1518,32 @@ Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
   else
     [panel setNameFieldStringValue: @""];
 
-  ret = [panel runModal];
 #else
-  if (NILP (mustmatch) && NILP (dir_only_p))
-    {
-      ret = [panel runModalForDirectory: dirS file: initS];
-    }
-  else
-    {
-      ret = [panel runModalForDirectory: dirS file: initS types: nil];
-    }
+  ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p);
+  ns_fd_data.dirS = dirS;
+  ns_fd_data.initS = initS;
 #endif
 
-  ret = (ret == NSOKButton) || panelOK;
+  /* runModalForDirectory/runModal restarts the main event loop when done,
+     so we must start an event loop and then pop up the file dialog.
+     The file dialog may pop up a confirm dialog after Ok has been pressed,
+     so we can not simply pop down on the Ok/Cancel press.
+   */
+  nxev = [NSEvent otherEventWithType: NSApplicationDefined
+                            location: NSMakePoint (0, 0)
+                       modifierFlags: 0
+                           timestamp: 0
+                        windowNumber: [[NSApp mainWindow] windowNumber]
+                             context: [NSApp context]
+                             subtype: 0
+                               data1: 0
+                               data2: NSAPP_DATA2_RUNFILEDIALOG];
+
+  [NSApp postEvent: nxev atStart: NO];
+  while (ns_fd_data.panel != nil)
+    [NSApp run];
+
+  ret = (ns_fd_data.ret == NSOKButton);
 
   if (ret)
     {
@@ -1757,10 +1823,10 @@ terminate Emacs if we can't open the connection.
   if (dpyinfo == 0)
     {
       if (!NILP (must_succeed))
-        fatal ("OpenStep on %s not responding.\n",
+        fatal ("Display on %s not responding.\n",
                SSDATA (display));
       else
-        error ("OpenStep on %s not responding.\n",
+        error ("Display on %s not responding.\n",
                SSDATA (display));
     }
 
@@ -1786,11 +1852,11 @@ DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
        doc: /* Return the list of display names that Emacs has connections to.  */)
      (void)
 {
-  Lisp_Object tail, result;
+  Lisp_Object result = Qnil;
+  struct ns_display_info *ndi;
 
-  result = Qnil;
-  for (tail = ns_display_name_list; CONSP (tail); tail = XCDR (tail))
-    result = Fcons (XCAR (XCAR (tail)), result);
+  for (ndi = x_display_list; ndi; ndi = ndi->next)
+    result = Fcons (XCAR (ndi->name_list_element), result);
 
   return result;
 }
@@ -1975,7 +2041,7 @@ there was no result.  */)
   ns_string_to_pasteboard (pb, send);
 
   if (NSPerformService (svcName, pb) == NO)
-    Fsignal (Qquit, Fcons (build_string ("service not available"), Qnil));
+    Fsignal (Qquit, list1 (build_string ("service not available")));
 
   if ([[pb types] count] == 0)
     return build_string ("");
@@ -1991,13 +2057,28 @@ DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
          remove this. */
   NSString *utfStr;
+  Lisp_Object ret = Qnil;
+  NSAutoreleasePool *pool;
 
   CHECK_STRING (str);
+  pool = [[NSAutoreleasePool alloc] init];
   utfStr = [NSString stringWithUTF8String: SSDATA (str)];
 #ifdef NS_IMPL_COCOA
+  if (utfStr)
     utfStr = [utfStr precomposedStringWithCanonicalMapping];
 #endif
-  return build_string ([utfStr UTF8String]);
+  if (utfStr)
+    {
+      const char *cstr = [utfStr UTF8String];
+      if (cstr)
+        ret = build_string (cstr);
+    }
+
+  [pool release];
+  if (NILP (ret))
+    error ("Invalid UTF-8");
+
+  return ret;
 }
 
 
@@ -2021,7 +2102,6 @@ ns_do_applescript (Lisp_Object script, Lisp_Object *result)
 
   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
   [scriptObject release];
-
   *result = Qnil;
 
   if (returnDescriptor != NULL)
@@ -2082,6 +2162,7 @@ In case the execution fails, an error is signaled. */)
   Lisp_Object result;
   int status;
   NSEvent *nxev;
+  struct input_event ev;
 
   CHECK_STRING (script);
   check_window_system (NULL);
@@ -2109,8 +2190,10 @@ In case the execution fails, an error is signaled. */)
 
   // If there are other events, the event loop may exit.  Keep running
   // until the script has been handled.  */
+  ns_init_events (&ev);
   while (! NILP (as_script))
     [NSApp run];
+  ns_finish_events ();
 
   status = as_status;
   as_status = 0;
@@ -2150,17 +2233,13 @@ x_set_scroll_bar_default_width (struct frame *f)
                                       wid - 1) / wid;
 }
 
-
-extern const char *x_get_string_resource (XrmDatabase, char *, char *);
-
-
 /* terms impl this instead of x-get-resource directly */
-const char *
-x_get_string_resource (XrmDatabase rdb, char *name, char *class)
+char *
+x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
 {
   /* remove appname prefix; TODO: allow for !="Emacs" */
-  char *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
-  const char *res;
+  const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
+
   check_window_system (NULL);
 
   if (inhibit_x_resources)
@@ -2168,16 +2247,16 @@ x_get_string_resource (XrmDatabase rdb, char *name, char *class)
     return NULL;
 
   res = ns_get_defaults_value (toCheck);
-  return !res ? NULL :
-      (!c_strncasecmp (res, "YES", 3) ? "true" :
-          (!c_strncasecmp (res, "NO", 2) ? "false" : res));
+  return (!res ? NULL :
+         (!c_strncasecmp (res, "YES", 3) ? "true" :
+          (!c_strncasecmp (res, "NO", 2) ? "false" : (char *) res)));
 }
 
 
 Lisp_Object
 x_get_focus_frame (struct frame *frame)
 {
-  struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
+  struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
   Lisp_Object nsfocus;
 
   if (!dpyinfo->x_focus_frame)
@@ -2187,30 +2266,6 @@ x_get_focus_frame (struct frame *frame)
   return nsfocus;
 }
 
-
-int
-x_pixel_width (struct frame *f)
-{
-  return FRAME_PIXEL_WIDTH (f);
-}
-
-
-int
-x_pixel_height (struct frame *f)
-{
-  return FRAME_PIXEL_HEIGHT (f);
-}
-
-
-void
-x_sync (struct frame *f)
-{
-  /* XXX Not implemented XXX */
-  return;
-}
-
-
-
 /* ==========================================================================
 
     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
@@ -2242,7 +2297,7 @@ DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
   if (ns_lisp_to_color (color, &col))
     return Qnil;
 
-  [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
+  [[col colorUsingDefaultColorSpace]
         getRed: &red green: &green blue: &blue alpha: &alpha];
   return list3i (lrint (red * 65280), lrint (green * 65280),
                 lrint (blue * 65280));
@@ -2320,28 +2375,86 @@ each physical monitor, use `display-monitor-attributes-list'.  */)
 }
 
 #ifdef NS_IMPL_COCOA
-/* Returns the name for the screen that DICT came from, or NULL.
+
+/* Returns the name for the screen that OBJ represents, or NULL.
    Caller must free return value.
 */
 
 static char *
-ns_screen_name (CGDirectDisplayID did)
+ns_get_name_from_ioreg (io_object_t obj)
 {
   char *name = NULL;
+
   NSDictionary *info = (NSDictionary *)
-    IODisplayCreateInfoDictionary (CGDisplayIOServicePort (did),
-                                   kIODisplayOnlyPreferredName);
-  NSDictionary *names
-    = [info objectForKey:
-              [NSString stringWithUTF8String:kDisplayProductName]];
-
-  if ([names count] > 0) {
-    NSString *n = [names objectForKey: [[names allKeys] objectAtIndex:0]];
-    if (n != nil)
-      name = xstrdup ([n UTF8String]);
-  }
+    IODisplayCreateInfoDictionary (obj, kIODisplayOnlyPreferredName);
+  NSDictionary *names = [info objectForKey:
+                                [NSString stringWithUTF8String:
+                                            kDisplayProductName]];
+
+  if ([names count] > 0)
+    {
+      NSString *n = [names objectForKey: [[names allKeys]
+                                                 objectAtIndex:0]];
+      if (n != nil) name = xstrdup ([n UTF8String]);
+    }
 
   [info release];
+
+  return name;
+}
+
+/* Returns the name for the screen that DID came from, or NULL.
+   Caller must free return value.
+*/
+
+static char *
+ns_screen_name (CGDirectDisplayID did)
+{
+  char *name = NULL;
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
+  mach_port_t masterPort;
+  io_iterator_t it;
+  io_object_t obj;
+
+  // CGDisplayIOServicePort is deprecated.  Do it another (harder) way.
+
+  if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess
+      || IOServiceGetMatchingServices (masterPort,
+                                       IOServiceMatching ("IONDRVDevice"),
+                                       &it) != kIOReturnSuccess)
+    return name;
+
+  /* Must loop until we find a name.  Many devices can have the same unit
+     number (represents different GPU parts), but only one has a name.  */
+  while (! name && (obj = IOIteratorNext (it)))
+    {
+      CFMutableDictionaryRef props;
+      const void *val;
+
+      if (IORegistryEntryCreateCFProperties (obj,
+                                             &props,
+                                             kCFAllocatorDefault,
+                                             kNilOptions) == kIOReturnSuccess
+          && props != nil
+          && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex")))
+        {
+          unsigned nr = [(NSNumber *)val unsignedIntegerValue];
+          if (nr == CGDisplayUnitNumber (did))
+            name = ns_get_name_from_ioreg (obj);
+        }
+
+      CFRelease (props);
+      IOObjectRelease (obj);
+    }
+
+  IOObjectRelease (it);
+
+#else
+
+  name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did));
+
+#endif
   return name;
 }
 #endif
@@ -2418,7 +2531,7 @@ Internal use only, use `display-monitor-attributes-list' instead.  */)
   if (n_monitors == 0)
     return Qnil;
 
-  monitors = (struct MonitorInfo *) xzalloc (n_monitors * sizeof (*monitors));
+  monitors = xzalloc (n_monitors * sizeof *monitors);
 
   for (i = 0; i < [screens count]; ++i)
     {
@@ -2446,7 +2559,7 @@ Internal use only, use `display-monitor-attributes-list' instead.  */)
           vy = (short) (primary_display_height -
                         vfr.size.height - vfr.origin.y);
         }
-      
+
       m->geom.x = (short) fr.origin.x;
       m->geom.y = y;
       m->geom.width = (unsigned short) fr.size.width;
@@ -2531,6 +2644,7 @@ compute_tip_xy (struct frame *f,
 {
   Lisp_Object left, top;
   EmacsView *view = FRAME_NS_VIEW (f);
+  struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
   NSPoint pt;
 
   /* Start with user-specified or mouse position.  */
@@ -2539,7 +2653,8 @@ compute_tip_xy (struct frame *f,
 
   if (!INTEGERP (left) || !INTEGERP (top))
     {
-      pt = last_mouse_motion_position;
+      pt.x = dpyinfo->last_mouse_motion_x;
+      pt.y = dpyinfo->last_mouse_motion_y;
       /* Convert to screen coordinates */
       pt = [view convertPoint: pt toView: nil];
       pt = [[view window] convertBaseToScreen: pt];
@@ -2548,7 +2663,7 @@ compute_tip_xy (struct frame *f,
     {
       /* Absolute coordinates.  */
       pt.x = XINT (left);
-      pt.y = x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)) - XINT (top)
+      pt.y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - XINT (top)
         - height;
     }
 
@@ -2558,7 +2673,7 @@ compute_tip_xy (struct frame *f,
   else if (pt.x + XINT (dx) <= 0)
     *root_x = 0; /* Can happen for negative dx */
   else if (pt.x + XINT (dx) + width
-          <= x_display_pixel_width (FRAME_NS_DISPLAY_INFO (f)))
+          <= x_display_pixel_width (FRAME_DISPLAY_INFO (f)))
     /* It fits to the right of the pointer.  */
     *root_x = pt.x + XINT (dx);
   else if (width + XINT (dx) <= pt.x)
@@ -2574,12 +2689,12 @@ compute_tip_xy (struct frame *f,
     /* It fits below the pointer.  */
     *root_y = pt.y - height - XINT (dy);
   else if (pt.y + XINT (dy) + height
-          <= x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)))
+          <= x_display_pixel_height (FRAME_DISPLAY_INFO (f)))
     /* It fits above the pointer */
       *root_y = pt.y + XINT (dy);
   else
     /* Put it on the top.  */
-    *root_y = x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)) - height;
+    *root_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height;
 }
 
 
@@ -2611,11 +2726,11 @@ Text larger than the specified size is clipped.  */)
 {
   int root_x, root_y;
   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
-  ptrdiff_t count = SPECPDL_INDEX ();
   struct frame *f;
   char *str;
   NSSize size;
 
+  dynwind_begin ();
   specbind (Qinhibit_redisplay, Qt);
 
   GCPRO4 (string, parms, frame, timeout);
@@ -2656,7 +2771,8 @@ Text larger than the specified size is clipped.  */)
   unblock_input ();
 
   UNGCPRO;
-  return unbind_to (count, Qnil);
+  dynwind_end ();
+  return Qnil;
 }
 
 
@@ -2755,25 +2871,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
 }
 
 @implementation EmacsSavePanel
-#ifdef NS_IMPL_COCOA
-/* --------------------------------------------------------------------------
-   These are overridden to intercept on OS X: ending panel restarts NSApp
-   event loop if it is stopped.  Not sure if this is correct behavior,
-   perhaps should check if running and if so send an appdefined.
-   -------------------------------------------------------------------------- */
-- (void) ok: (id)sender
-{
-  [super ok: sender];
-  panelOK = 1;
-  [NSApp stop: self];
-}
-- (void) cancel: (id)sender
-{
-  [super cancel: sender];
-  [NSApp stop: self];
-}
-#endif
-
 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
 {
   BOOL ret = handlePanelKeys (self, theEvent);
@@ -2785,31 +2882,6 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
 
 
 @implementation EmacsOpenPanel
-#ifdef NS_IMPL_COCOA
-/* --------------------------------------------------------------------------
-   These are overridden to intercept on OS X: ending panel restarts NSApp
-   event loop if it is stopped.  Not sure if this is correct behavior,
-   perhaps should check if running and if so send an appdefined.
-   -------------------------------------------------------------------------- */
-- (void) ok: (id)sender
-{
-  [super ok: sender];
-
-  // If not choosing directories, and Open is pressed on a directory, return.
-  if (! [self canChooseDirectories] && ns_directory_from_panel (self) &&
-      ! ns_filename_from_panel (self))
-    return;
-
-  panelOK = 1;
-  [NSApp stop: self];
-}
-- (void) cancel: (id)sender
-{
-  [super cancel: sender];
-  [NSApp stop: self];
-}
-
-#endif
 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
 {
   // NSOpenPanel inherits NSSavePanel, so passing self is OK.
@@ -2853,6 +2925,8 @@ handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
 void
 syms_of_nsfns (void)
 {
+#include "nsfns.x"
+
   Qfontsize = intern_c_string ("fontsize");
   staticpro (&Qfontsize);
 
@@ -2875,56 +2949,12 @@ Example: Install an icon Gnus.tiff and execute the following code
 
 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
 be used as the image of the icon representing the frame.  */);
-  Vns_icon_type_alist = Fcons (Qt, Qnil);
+  Vns_icon_type_alist = list1 (Qt);
 
   DEFVAR_LISP ("ns-version-string", Vns_version_string,
                doc: /* Toolkit version for NS Windowing.  */);
   Vns_version_string = ns_appkit_version_str ();
 
-  defsubr (&Sns_read_file_name);
-  defsubr (&Sns_get_resource);
-  defsubr (&Sns_set_resource);
-  defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
-  defsubr (&Sx_display_grayscale_p);
-  defsubr (&Sns_font_name);
-  defsubr (&Sns_list_colors);
-#ifdef NS_IMPL_COCOA
-  defsubr (&Sns_do_applescript);
-#endif
-  defsubr (&Sxw_color_defined_p);
-  defsubr (&Sxw_color_values);
-  defsubr (&Sx_server_max_request_size);
-  defsubr (&Sx_server_vendor);
-  defsubr (&Sx_server_version);
-  defsubr (&Sx_display_pixel_width);
-  defsubr (&Sx_display_pixel_height);
-  defsubr (&Sns_display_monitor_attributes_list);
-  defsubr (&Sx_display_mm_width);
-  defsubr (&Sx_display_mm_height);
-  defsubr (&Sx_display_screens);
-  defsubr (&Sx_display_planes);
-  defsubr (&Sx_display_color_cells);
-  defsubr (&Sx_display_visual_class);
-  defsubr (&Sx_display_backing_store);
-  defsubr (&Sx_display_save_under);
-  defsubr (&Sx_create_frame);
-  defsubr (&Sx_open_connection);
-  defsubr (&Sx_close_connection);
-  defsubr (&Sx_display_list);
-
-  defsubr (&Sns_hide_others);
-  defsubr (&Sns_hide_emacs);
-  defsubr (&Sns_emacs_info_panel);
-  defsubr (&Sns_list_services);
-  defsubr (&Sns_perform_service);
-  defsubr (&Sns_convert_utf8_nfd_to_nfc);
-  defsubr (&Sx_focus_frame);
-  defsubr (&Sns_popup_font_panel);
-  defsubr (&Sns_popup_color_panel);
-
-  defsubr (&Sx_show_tip);
-  defsubr (&Sx_hide_tip);
-
   as_status = 0;
   as_script = Qnil;
   as_result = 0;