Fix memory leak warning.
[bpt/emacs.git] / src / nsfns.m
index 1e07599..ba0dba8 100644 (file)
@@ -89,9 +89,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 */
@@ -146,7 +143,7 @@ check_ns_display_info (Lisp_Object object)
     dpyinfo = ns_display_info_for_name (object);
   else
     {
-      FRAME_PTR f = decode_window_system_frame (object);
+      struct frame *f = decode_window_system_frame (object);
       dpyinfo = FRAME_NS_DISPLAY_INFO (f);
     }
 
@@ -434,7 +431,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;
@@ -506,7 +503,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 +514,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);
 
@@ -860,7 +857,7 @@ 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);
 
@@ -888,7 +885,7 @@ ns_appkit_version_str (void)
 
 #ifdef NS_IMPL_GNUSTEP
   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
-#elif defined(NS_IMPL_COCOA)
+#elif defined (NS_IMPL_COCOA)
   sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber);
 #else
   tmp = "ns-unknown";
@@ -905,7 +902,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;
@@ -984,7 +981,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,7 +990,7 @@ 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)))
@@ -1009,10 +1006,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;
 }
 
 /*
@@ -1074,7 +1068,7 @@ 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;
@@ -1396,6 +1390,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 +1449,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 +1470,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 +1483,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 +1496,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)
     {
@@ -1975,7 +2019,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 +2035,17 @@ 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;
 
   CHECK_STRING (str);
-  utfStr = [NSString stringWithUTF8String: SSDATA (str)];
+  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+ utfStr = [NSString stringWithUTF8String: SSDATA (str)];
 #ifdef NS_IMPL_COCOA
-    utfStr = [utfStr precomposedStringWithCanonicalMapping];
+  utfStr = [utfStr precomposedStringWithCanonicalMapping];
 #endif
-  return build_string ([utfStr UTF8String]);
+  ret = build_string ([utfStr UTF8String]);
+  [pool release];
+  return ret;
 }
 
 
@@ -2187,21 +2235,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)
 {
@@ -2418,7 +2451,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 +2479,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;
@@ -2755,25 +2788,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 +2799,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.
@@ -2875,7 +2864,7 @@ 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.  */);